This commit is contained in:
lifestorm
2024-08-04 23:12:27 +03:00
parent 0e770b2b49
commit ba1fc01b16
7084 changed files with 2173495 additions and 14 deletions

View File

@@ -0,0 +1,406 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
function GM:HandlePlayerJumping( ply, velocity, plyTable )
if ( !plyTable ) then plyTable = ply:GetTable() end
if ( ply:GetMoveType() == MOVETYPE_NOCLIP ) then
plyTable.m_bJumping = false
return
end
-- airwalk more like hl2mp, we airwalk until we have 0 velocity, then it's the jump animation
-- underwater we're alright we airwalking
if ( !plyTable.m_bJumping && !ply:OnGround() && ply:WaterLevel() <= 0 ) then
if ( !plyTable.m_fGroundTime ) then
plyTable.m_fGroundTime = CurTime()
elseif ( ( CurTime() - plyTable.m_fGroundTime ) > 0 && velocity:Length2DSqr() < 0.25 ) then
plyTable.m_bJumping = true
plyTable.m_bFirstJumpFrame = false
plyTable.m_flJumpStartTime = 0
end
end
if ( plyTable.m_bJumping ) then
if ( plyTable.m_bFirstJumpFrame ) then
plyTable.m_bFirstJumpFrame = false
ply:AnimRestartMainSequence()
end
if ( ( ply:WaterLevel() >= 2 ) || ( ( CurTime() - plyTable.m_flJumpStartTime ) > 0.2 && ply:OnGround() ) ) then
plyTable.m_bJumping = false
plyTable.m_fGroundTime = nil
ply:AnimRestartMainSequence()
end
if ( plyTable.m_bJumping ) then
plyTable.CalcIdeal = ACT_MP_JUMP
return true
end
end
return false
end
function GM:HandlePlayerDucking( ply, velocity, plyTable )
if ( !plyTable ) then plyTable = ply:GetTable() end
if ( !ply:IsFlagSet( FL_ANIMDUCKING ) ) then return false end
if ( velocity:Length2DSqr() > 0.25 ) then
plyTable.CalcIdeal = ACT_MP_CROUCHWALK
else
plyTable.CalcIdeal = ACT_MP_CROUCH_IDLE
end
return true
end
function GM:HandlePlayerNoClipping( ply, velocity, plyTable )
if ( !plyTable ) then plyTable = ply:GetTable() end
if ( ply:GetMoveType() != MOVETYPE_NOCLIP || ply:InVehicle() ) then
if ( plyTable.m_bWasNoclipping ) then
plyTable.m_bWasNoclipping = nil
ply:AnimResetGestureSlot( GESTURE_SLOT_CUSTOM )
if ( CLIENT ) then ply:SetIK( true ) end
end
return
end
if ( !plyTable.m_bWasNoclipping ) then
ply:AnimRestartGesture( GESTURE_SLOT_CUSTOM, ACT_GMOD_NOCLIP_LAYER, false )
if ( CLIENT ) then ply:SetIK( false ) end
end
return true
end
function GM:HandlePlayerVaulting( ply, velocity, plyTable )
if ( !plyTable ) then plyTable = ply:GetTable() end
if ( velocity:LengthSqr() < 1000000 ) then return end
if ( ply:IsOnGround() ) then return end
plyTable.CalcIdeal = ACT_MP_SWIM
return true
end
function GM:HandlePlayerSwimming( ply, velocity, plyTable )
if ( !plyTable ) then plyTable = ply:GetTable() end
if ( ply:WaterLevel() < 2 || ply:IsOnGround() ) then
plyTable.m_bInSwim = false
return false
end
plyTable.CalcIdeal = ACT_MP_SWIM
plyTable.m_bInSwim = true
return true
end
function GM:HandlePlayerLanding( ply, velocity, WasOnGround )
if ( ply:GetMoveType() == MOVETYPE_NOCLIP ) then return end
if ( ply:IsOnGround() && !WasOnGround ) then
ply:AnimRestartGesture( GESTURE_SLOT_JUMP, ACT_LAND, true )
end
end
function GM:HandlePlayerDriving( ply, plyTable )
if ( !plyTable ) then plyTable = ply:GetTable() end
-- The player must have a parent to be in a vehicle. If there's no parent, we are in the exit anim, so don't do sitting in 3rd person anymore
if ( !ply:InVehicle() || !IsValid( ply:GetParent() ) ) then return false end
local pVehicle = ply:GetVehicle()
if ( !pVehicle.HandleAnimation && pVehicle.GetVehicleClass ) then
local c = pVehicle:GetVehicleClass()
local t = list.Get( "Vehicles" )[ c ]
if ( t && t.Members && t.Members.HandleAnimation ) then
pVehicle.HandleAnimation = t.Members.HandleAnimation
else
pVehicle.HandleAnimation = true -- Prevent this if block from trying to assign HandleAnimation again.
end
end
if ( isfunction( pVehicle.HandleAnimation ) ) then
local seq = pVehicle:HandleAnimation( ply )
if ( seq != nil ) then
plyTable.CalcSeqOverride = seq
end
end
if ( plyTable.CalcSeqOverride == -1 ) then -- pVehicle.HandleAnimation did not give us an animation
local class = pVehicle:GetClass()
if ( class == "prop_vehicle_jeep" ) then
plyTable.CalcSeqOverride = ply:LookupSequence( "drive_jeep" )
elseif ( class == "prop_vehicle_airboat" ) then
plyTable.CalcSeqOverride = ply:LookupSequence( "drive_airboat" )
elseif ( class == "prop_vehicle_prisoner_pod" && pVehicle:GetModel() == "models/vehicles/prisoner_pod_inner.mdl" ) then
-- HACK!!
plyTable.CalcSeqOverride = ply:LookupSequence( "drive_pd" )
else
plyTable.CalcSeqOverride = ply:LookupSequence( "sit_rollercoaster" )
end
end
local use_anims = ( plyTable.CalcSeqOverride == ply:LookupSequence( "sit_rollercoaster" ) || plyTable.CalcSeqOverride == ply:LookupSequence( "sit" ) )
if ( use_anims && ply:GetAllowWeaponsInVehicle() && IsValid( ply:GetActiveWeapon() ) ) then
local holdtype = ply:GetActiveWeapon():GetHoldType()
if ( holdtype == "smg" ) then holdtype = "smg1" end
local seqid = ply:LookupSequence( "sit_" .. holdtype )
if ( seqid != -1 ) then
plyTable.CalcSeqOverride = seqid
end
end
return true
end
--[[---------------------------------------------------------
Name: gamemode:UpdateAnimation()
Desc: Animation updates (pose params etc) should be done here
-----------------------------------------------------------]]
function GM:UpdateAnimation( ply, velocity, maxseqgroundspeed )
local len = velocity:Length()
local movement = 1.0
if ( len > 0.2 ) then
movement = ( len / maxseqgroundspeed )
end
local rate = math.min( movement, 2 )
-- if we're under water we want to constantly be swimming..
if ( ply:WaterLevel() >= 2 ) then
rate = math.max( rate, 0.5 )
elseif ( !ply:IsOnGround() && len >= 1000 ) then
rate = 0.1
end
ply:SetPlaybackRate( rate )
-- We only need to do this clientside..
if ( CLIENT ) then
if ( ply:InVehicle() ) then
--
-- This is used for the 'rollercoaster' arms
--
local Vehicle = ply:GetVehicle()
local Velocity = Vehicle:GetVelocity()
local fwd = Vehicle:GetUp()
local dp = fwd:Dot( Vector( 0, 0, 1 ) )
ply:SetPoseParameter( "vertical_velocity", ( dp < 0 && dp || 0 ) + fwd:Dot( Velocity ) * 0.005 )
-- Pass the vehicles steer param down to the player
local steer = Vehicle:GetPoseParameter( "vehicle_steer" )
steer = steer * 2 - 1 -- convert from 0..1 to -1..1
if ( Vehicle:GetClass() == "prop_vehicle_prisoner_pod" ) then steer = 0 ply:SetPoseParameter( "aim_yaw", math.NormalizeAngle( ply:GetAimVector():Angle().y - Vehicle:GetAngles().y - 90 ) ) end
ply:SetPoseParameter( "vehicle_steer", steer )
end
GAMEMODE:GrabEarAnimation( ply )
GAMEMODE:MouthMoveAnimation( ply )
end
end
--
-- If you don't want the player to grab his ear in your gamemode then
-- just override this.
--
function GM:GrabEarAnimation( ply, plyTable )
if ( !plyTable ) then plyTable = ply:GetTable() end
plyTable.ChatGestureWeight = plyTable.ChatGestureWeight || 0
-- Don't show this when we're playing a taunt!
if ( ply:IsPlayingTaunt() ) then return end
if ( ply:IsTyping() ) then
plyTable.ChatGestureWeight = math.Approach( plyTable.ChatGestureWeight, 1, FrameTime() * 5.0 )
else
plyTable.ChatGestureWeight = math.Approach( plyTable.ChatGestureWeight, 0, FrameTime() * 5.0 )
end
if ( plyTable.ChatGestureWeight > 0 ) then
ply:AnimRestartGesture( GESTURE_SLOT_VCD, ACT_GMOD_IN_CHAT, true )
ply:AnimSetGestureWeight( GESTURE_SLOT_VCD, plyTable.ChatGestureWeight )
end
end
--
-- Moves the mouth when talking on voicecom
--
function GM:MouthMoveAnimation( ply )
local flexes = {
ply:GetFlexIDByName( "jaw_drop" ),
ply:GetFlexIDByName( "left_part" ),
ply:GetFlexIDByName( "right_part" ),
ply:GetFlexIDByName( "left_mouth_drop" ),
ply:GetFlexIDByName( "right_mouth_drop" )
}
local weight = ply:IsSpeaking() && math.Clamp( ply:VoiceVolume() * 2, 0, 2 ) || 0
for k, v in ipairs( flexes ) do
ply:SetFlexWeight( v, weight )
end
end
function GM:CalcMainActivity( ply, velocity )
local plyTable = ply:GetTable()
plyTable.CalcIdeal = ACT_MP_STAND_IDLE
plyTable.CalcSeqOverride = -1
self:HandlePlayerLanding( ply, velocity, plyTable.m_bWasOnGround )
if !( self:HandlePlayerNoClipping( ply, velocity, plyTable ) ||
self:HandlePlayerDriving( ply, plyTable ) ||
self:HandlePlayerVaulting( ply, velocity, plyTable ) ||
self:HandlePlayerJumping( ply, velocity, plyTable ) ||
self:HandlePlayerSwimming( ply, velocity, plyTable ) ||
self:HandlePlayerDucking( ply, velocity, plyTable ) ) then
local len2d = velocity:Length2DSqr()
if ( len2d > 22500 ) then plyTable.CalcIdeal = ACT_MP_RUN elseif ( len2d > 0.25 ) then plyTable.CalcIdeal = ACT_MP_WALK end
end
plyTable.m_bWasOnGround = ply:IsOnGround()
plyTable.m_bWasNoclipping = ( ply:GetMoveType() == MOVETYPE_NOCLIP && !ply:InVehicle() )
return plyTable.CalcIdeal, plyTable.CalcSeqOverride
end
local IdleActivity = ACT_HL2MP_IDLE
local IdleActivityTranslate = {}
IdleActivityTranslate[ ACT_MP_STAND_IDLE ] = IdleActivity
IdleActivityTranslate[ ACT_MP_WALK ] = IdleActivity + 1
IdleActivityTranslate[ ACT_MP_RUN ] = IdleActivity + 2
IdleActivityTranslate[ ACT_MP_CROUCH_IDLE ] = IdleActivity + 3
IdleActivityTranslate[ ACT_MP_CROUCHWALK ] = IdleActivity + 4
IdleActivityTranslate[ ACT_MP_ATTACK_STAND_PRIMARYFIRE ] = IdleActivity + 5
IdleActivityTranslate[ ACT_MP_ATTACK_CROUCH_PRIMARYFIRE ] = IdleActivity + 5
IdleActivityTranslate[ ACT_MP_RELOAD_STAND ] = IdleActivity + 6
IdleActivityTranslate[ ACT_MP_RELOAD_CROUCH ] = IdleActivity + 6
IdleActivityTranslate[ ACT_MP_JUMP ] = ACT_HL2MP_JUMP_SLAM
IdleActivityTranslate[ ACT_MP_SWIM ] = IdleActivity + 9
IdleActivityTranslate[ ACT_LAND ] = ACT_LAND
-- it is preferred you return ACT_MP_* in CalcMainActivity, and if you have a specific need to not translate through the weapon do it here
function GM:TranslateActivity( ply, act )
local newact = ply:TranslateWeaponActivity( act )
-- select idle anims if the weapon didn't decide
if ( act == newact ) then
return IdleActivityTranslate[ act ]
end
return newact
end
function GM:DoAnimationEvent( ply, event, data )
if ( event == PLAYERANIMEVENT_ATTACK_PRIMARY ) then
if ply:IsFlagSet( FL_ANIMDUCKING ) then
ply:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, true )
else
ply:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_STAND_PRIMARYFIRE, true )
end
return ACT_VM_PRIMARYATTACK
elseif ( event == PLAYERANIMEVENT_ATTACK_SECONDARY ) then
-- there is no gesture, so just fire off the VM event
return ACT_VM_SECONDARYATTACK
elseif ( event == PLAYERANIMEVENT_RELOAD ) then
if ply:IsFlagSet( FL_ANIMDUCKING ) then
ply:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_CROUCH, true )
else
ply:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_STAND, true )
end
return ACT_INVALID
elseif ( event == PLAYERANIMEVENT_JUMP ) then
ply.m_bJumping = true
ply.m_bFirstJumpFrame = true
ply.m_flJumpStartTime = CurTime()
ply:AnimRestartMainSequence()
return ACT_INVALID
elseif ( event == PLAYERANIMEVENT_CANCEL_RELOAD ) then
ply:AnimResetGestureSlot( GESTURE_SLOT_ATTACK_AND_RELOAD )
return ACT_INVALID
end
end

View File

@@ -0,0 +1,302 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local hud_deathnotice_time = CreateConVar( "hud_deathnotice_time", "6", FCVAR_REPLICATED, "Amount of time to show death notice (kill feed) for" )
local cl_drawhud = GetConVar( "cl_drawhud" )
-- These are our kill icons
local Color_Icon = Color( 255, 80, 0, 255 )
local NPC_Color_Enemy = Color( 250, 50, 50, 255 )
local NPC_Color_Friendly = Color( 50, 200, 50, 255 )
killicon.AddFont( "prop_physics", "HL2MPTypeDeath", "9", Color_Icon, 0.52 )
killicon.AddFont( "weapon_smg1", "HL2MPTypeDeath", "/", Color_Icon, 0.55 )
killicon.AddFont( "weapon_357", "HL2MPTypeDeath", ".", Color_Icon, 0.55 )
killicon.AddFont( "weapon_ar2", "HL2MPTypeDeath", "2", Color_Icon, 0.6 )
killicon.AddFont( "crossbow_bolt", "HL2MPTypeDeath", "1", Color_Icon, 0.5 )
killicon.AddFont( "weapon_shotgun", "HL2MPTypeDeath", "0", Color_Icon, 0.45 )
killicon.AddFont( "rpg_missile", "HL2MPTypeDeath", "3", Color_Icon, 0.35 )
killicon.AddFont( "npc_grenade_frag", "HL2MPTypeDeath", "4", Color_Icon, 0.56 )
killicon.AddFont( "weapon_pistol", "HL2MPTypeDeath", "-", Color_Icon, 0.52 )
killicon.AddFont( "prop_combine_ball", "HL2MPTypeDeath", "8", Color_Icon, 0.5 )
killicon.AddFont( "grenade_ar2", "HL2MPTypeDeath", "7", Color_Icon, 0.35 )
killicon.AddFont( "weapon_stunstick", "HL2MPTypeDeath", "!", Color_Icon, 0.6 )
killicon.AddFont( "npc_satchel", "HL2MPTypeDeath", "*", Color_Icon, 0.53 )
killicon.AddAlias( "npc_tripmine", "npc_satchel" )
killicon.AddFont( "weapon_crowbar", "HL2MPTypeDeath", "6", Color_Icon, 0.45 )
killicon.AddFont( "weapon_physcannon", "HL2MPTypeDeath", ",", Color_Icon, 0.55 )
-- Prop like objects get the prop kill icon
killicon.AddAlias( "prop_ragdoll", "prop_physics" )
killicon.AddAlias( "prop_physics_respawnable", "prop_physics" )
killicon.AddAlias( "func_physbox", "prop_physics" )
killicon.AddAlias( "func_physbox_multiplayer", "prop_physics" )
killicon.AddAlias( "trigger_vphysics_motion", "prop_physics" )
killicon.AddAlias( "func_movelinear", "prop_physics" )
killicon.AddAlias( "func_plat", "prop_physics" )
killicon.AddAlias( "func_platrot", "prop_physics" )
killicon.AddAlias( "func_pushable", "prop_physics" )
killicon.AddAlias( "func_rotating", "prop_physics" )
killicon.AddAlias( "func_rot_button", "prop_physics" )
killicon.AddAlias( "func_tracktrain", "prop_physics" )
killicon.AddAlias( "func_train", "prop_physics" )
local function HandleAchievements( victimType )
-- Try to find by name
for id, tab in pairs( list.Get( "NPC" ) ) do
if ( tab.Name == victimType ) then
victimType = tab.Class
end
end
-- If fails, try to omit the translation system #
if ( victimType:StartsWith( "#" ) ) then
victimType = victimType:sub( 2 )
end
local bIsEnemy = IsEnemyEntityName( victimType )
local bIsFriend = IsFriendEntityName( victimType )
if ( bIsEnemy ) then
achievements.IncBaddies()
end
if ( bIsFriend ) then
achievements.IncGoodies()
end
if ( !bIsFriend && !bIsEnemy ) then
achievements.IncBystander()
end
end
-- Backwards compatiblity for addons
net.Receive( "PlayerKilledByPlayer", function()
local victim = net.ReadEntity()
local inflictor = net.ReadString()
local attacker = net.ReadEntity()
if ( !IsValid( attacker ) ) then return end
if ( !IsValid( victim ) ) then return end
hook.Run( "AddDeathNotice", attacker:Name(), attacker:Team(), inflictor, victim:Name(), victim:Team(), 0 )
end )
net.Receive( "PlayerKilledSelf", function()
local victim = net.ReadEntity()
if ( !IsValid( victim ) ) then return end
hook.Run( "AddDeathNotice", nil, 0, "suicide", victim:Name(), victim:Team(), 0 )
end )
net.Receive( "PlayerKilled", function()
local victim = net.ReadEntity()
if ( !IsValid( victim ) ) then return end
local inflictor = net.ReadString()
local attacker = net.ReadString()
hook.Run( "AddDeathNotice", "#" .. attacker, -1, inflictor, victim:Name(), victim:Team(), 0 )
end )
net.Receive( "PlayerKilledNPC", function()
local victimtype = net.ReadString()
local inflictor = net.ReadString()
local attacker = net.ReadEntity()
--
-- For some reason the killer isn't known to us, so don't proceed.
--
if ( !IsValid( attacker ) ) then return end
hook.Run( "AddDeathNotice", attacker:Name(), attacker:Team(), inflictor, "#" .. victimtype, -1, 0 )
local bIsLocalPlayer = ( IsValid( attacker ) && attacker == LocalPlayer() )
if ( bIsLocalPlayer ) then
HandleAchievements( victimtype )
end
end )
net.Receive( "NPCKilledNPC", function()
local victim = "#" .. net.ReadString()
local inflictor = net.ReadString()
local attacker = "#" .. net.ReadString()
hook.Run( "AddDeathNotice", attacker, -1, inflictor, victim, -1, 0 )
end )
-- The new way
DEATH_NOTICE_FRIENDLY_VICTIM = 1
DEATH_NOTICE_FRIENDLY_ATTACKER = 2
--DEATH_NOTICE_HEADSHOT = 4
--DEATH_NOTICE_PENETRATION = 8
net.Receive( "DeathNoticeEvent", function()
local attacker = nil
local attackerType = net.ReadUInt( 2 )
if ( attackerType == 1 ) then
attacker = net.ReadString()
elseif ( attackerType == 2 ) then
attacker = net.ReadEntity()
end
local inflictor = net.ReadString()
local victim = nil
local victimType = net.ReadUInt( 2 )
if ( victimType == 1 ) then
victim = net.ReadString()
elseif ( victimType == 2 ) then
victim = net.ReadEntity()
end
local flags = net.ReadUInt( 8 )
local bIsLocalPlayer = ( isentity( attacker ) && IsValid( attacker ) && attacker == LocalPlayer() )
if ( bIsLocalPlayer && isstring( victim ) ) then
HandleAchievements( victim )
end
local team_a = -1
local team_v = -1
if ( bit.band( flags, DEATH_NOTICE_FRIENDLY_VICTIM ) != 0 ) then team_v = -2 end
if ( bit.band( flags, DEATH_NOTICE_FRIENDLY_ATTACKER ) != 0 ) then team_a = -2 end
-- Handle player entities
if ( isentity( attacker ) and attacker:IsValid() and attacker:IsPlayer() ) then team_a = attacker:Team() attacker = attacker:Name() end
if ( isentity( victim ) and victim:IsValid() and victim:IsPlayer() ) then team_v = victim:Team() victim = victim:Name() end
-- Handle other entities
if ( isentity( attacker ) and attacker:IsValid() ) then attacker = attacker:GetClass() end
if ( isentity( victim ) and victim:IsValid() ) then victim = victim:GetClass() end
hook.Run( "AddDeathNotice", attacker, team_a, inflictor, victim, team_v, flags )
end )
local Deaths = {}
local function getDeathColor( teamID, target )
if ( teamID == -1 ) then
return table.Copy( NPC_Color_Enemy )
end
if ( teamID == -2 ) then
return table.Copy( NPC_Color_Friendly )
end
return table.Copy( team.GetColor( teamID ) )
end
--[[---------------------------------------------------------
Name: gamemode:AddDeathNotice( Attacker, team1, Inflictor, Victim, team2, flags )
Desc: Adds an death notice entry
-----------------------------------------------------------]]
function GM:AddDeathNotice( attacker, team1, inflictor, victim, team2, flags )
if ( inflictor == "suicide" ) then attacker = nil end
local Death = {}
Death.time = CurTime()
Death.left = attacker
Death.right = victim
Death.icon = inflictor
Death.flags = flags
Death.color1 = getDeathColor( team1, Death.left )
Death.color2 = getDeathColor( team2, Death.right )
table.insert( Deaths, Death )
end
local function DrawDeath( x, y, death, time )
local w, h = killicon.GetSize( death.icon )
if ( !w or !h ) then return end
local fadeout = ( death.time + time ) - CurTime()
local alpha = math.Clamp( fadeout * 255, 0, 255 )
death.color1.a = alpha
death.color2.a = alpha
-- Draw Icon
killicon.Render( x - w / 2, y, death.icon, alpha )
-- Draw KILLER
if ( death.left ) then
draw.SimpleText( death.left, "ChatFont", x - ( w / 2 ) - 16, y + h / 2, death.color1, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER )
end
-- Draw VICTIM
draw.SimpleText( death.right, "ChatFont", x + ( w / 2 ) + 16, y + h / 2, death.color2, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER )
return math.ceil( y + h * 0.75 )
-- Font killicons are too high when height corrected, and changing that is not backwards compatible
--return math.ceil( y + math.max( h, 28 ) )
end
function GM:DrawDeathNotice( x, y )
if ( cl_drawhud:GetInt() == 0 ) then return end
local time = hud_deathnotice_time:GetFloat()
local reset = Deaths[1] != nil -- Don't reset it if there's nothing in it
x = x * ScrW()
y = y * ScrH()
-- Draw
for k, Death in ipairs( Deaths ) do
if ( Death.time + time > CurTime() ) then
if ( Death.lerp ) then
x = x * 0.3 + Death.lerp.x * 0.7
y = y * 0.3 + Death.lerp.y * 0.7
end
Death.lerp = Death.lerp or {}
Death.lerp.x = x
Death.lerp.y = y
y = DrawDeath( math.floor( x ), math.floor( y ), Death, time )
reset = false
end
end
-- We want to maintain the order of the table so instead of removing
-- expired entries one by one we will just clear the entire table
-- once everything is expired.
if ( reset ) then
Deaths = {}
end
end

View File

@@ -0,0 +1,183 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
GM.PickupHistory = {}
GM.PickupHistoryLast = 0
GM.PickupHistoryTop = ScrH() / 2
GM.PickupHistoryWide = 300
GM.PickupHistoryCorner = surface.GetTextureID( "gui/corner8" )
local function AddGenericPickup( self, itemname )
local pickup = {}
pickup.time = CurTime()
pickup.name = itemname
pickup.holdtime = 5
pickup.font = "DermaDefaultBold"
pickup.fadein = 0.04
pickup.fadeout = 0.3
surface.SetFont( pickup.font )
local w, h = surface.GetTextSize( pickup.name )
pickup.height = h
pickup.width = w
--[[if ( self.PickupHistoryLast >= pickup.time ) then
pickup.time = self.PickupHistoryLast + 0.05
end]]
table.insert( self.PickupHistory, pickup )
self.PickupHistoryLast = pickup.time
return pickup
end
--[[---------------------------------------------------------
Name: gamemode:HUDWeaponPickedUp( wep )
Desc: The game wants you to draw on the HUD that a weapon has been picked up
-----------------------------------------------------------]]
function GM:HUDWeaponPickedUp( wep )
if ( !IsValid( LocalPlayer() ) || !LocalPlayer():Alive() ) then return end
if ( !IsValid( wep ) ) then return end
if ( !isfunction( wep.GetPrintName ) ) then return end
local pickup = AddGenericPickup( self, wep:GetPrintName() )
pickup.color = Color( 255, 200, 50, 255 )
end
--[[---------------------------------------------------------
Name: gamemode:HUDItemPickedUp( itemname )
Desc: An item has been picked up..
-----------------------------------------------------------]]
function GM:HUDItemPickedUp( itemname )
if ( !IsValid( LocalPlayer() ) || !LocalPlayer():Alive() ) then return end
local pickup = AddGenericPickup( self, "#" .. itemname )
pickup.color = Color( 180, 255, 180, 255 )
end
--[[---------------------------------------------------------
Name: gamemode:HUDAmmoPickedUp( itemname, amount )
Desc: Ammo has been picked up..
-----------------------------------------------------------]]
function GM:HUDAmmoPickedUp( itemname, amount )
if ( !IsValid( LocalPlayer() ) || !LocalPlayer():Alive() ) then return end
-- Try to tack it onto an exisiting ammo pickup
if ( self.PickupHistory ) then
for k, v in pairs( self.PickupHistory ) do
if ( v.name == "#" .. itemname .. "_ammo" ) then
v.amount = tostring( tonumber( v.amount ) + amount )
v.time = CurTime() - v.fadein
return
end
end
end
local pickup = AddGenericPickup( self, "#" .. itemname .. "_ammo" )
pickup.color = Color( 180, 200, 255, 255 )
pickup.amount = tostring( amount )
local w, h = surface.GetTextSize( pickup.amount )
pickup.width = pickup.width + w + 16
end
function GM:HUDDrawPickupHistory()
if ( self.PickupHistory == nil ) then return end
local x, y = ScrW() - self.PickupHistoryWide - 20, self.PickupHistoryTop
local tall = 0
local wide = 0
for k, v in pairs( self.PickupHistory ) do
if ( !istable( v ) ) then
Msg( tostring( v ) .. "\n" )
PrintTable( self.PickupHistory )
self.PickupHistory[ k ] = nil
return
end
if ( v.time < CurTime() ) then
if ( v.y == nil ) then v.y = y end
v.y = ( v.y * 5 + y ) / 6
local delta = ( v.time + v.holdtime ) - CurTime()
delta = delta / v.holdtime
local alpha = 255
local colordelta = math.Clamp( delta, 0.6, 0.7 )
-- Fade in/out
if ( delta > 1 - v.fadein ) then
alpha = math.Clamp( ( 1.0 - delta ) * ( 255 / v.fadein ), 0, 255 )
elseif ( delta < v.fadeout ) then
alpha = math.Clamp( delta * ( 255 / v.fadeout ), 0, 255 )
end
v.x = x + self.PickupHistoryWide - ( self.PickupHistoryWide * ( alpha / 255 ) )
local rx, ry, rw, rh = math.Round( v.x - 4 ), math.Round( v.y - ( v.height / 2 ) - 4 ), math.Round( self.PickupHistoryWide + 9 ), math.Round( v.height + 8 )
local bordersize = 8
surface.SetTexture( self.PickupHistoryCorner )
surface.SetDrawColor( v.color.r, v.color.g, v.color.b, alpha )
surface.DrawTexturedRectRotated( rx + bordersize / 2, ry + bordersize / 2, bordersize, bordersize, 0 )
surface.DrawTexturedRectRotated( rx + bordersize / 2, ry + rh -bordersize / 2, bordersize, bordersize, 90 )
surface.DrawRect( rx, ry + bordersize, bordersize, rh-bordersize * 2 )
surface.DrawRect( rx + bordersize, ry, v.height - 4, rh )
surface.SetDrawColor( 230 * colordelta, 230 * colordelta, 230 * colordelta, alpha )
surface.DrawTexturedRectRotated( rx + rw - bordersize / 2 , ry + rh - bordersize / 2, bordersize, bordersize, 180 )
surface.DrawTexturedRectRotated( rx + rw - bordersize / 2 , ry + bordersize / 2, bordersize, bordersize, 270 )
surface.DrawRect( rx + rw - bordersize, ry + bordersize, bordersize, rh-bordersize * 2 )
surface.DrawRect( rx + bordersize + v.height - 4, ry, rw - ( v.height - 4 ) - bordersize * 2, rh )
draw.SimpleText( v.name, v.font, v.x + v.height + 9, ry + ( rh / 2 ) + 1, Color( 0, 0, 0, alpha * 0.5 ), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER )
draw.SimpleText( v.name, v.font, v.x + v.height + 8, ry + ( rh / 2 ), Color( 255, 255, 255, alpha ), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER )
if ( v.amount ) then
draw.SimpleText( v.amount, v.font, v.x + self.PickupHistoryWide + 1, ry + ( rh / 2 ) + 1, Color( 0, 0, 0, alpha * 0.5 ), TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER )
draw.SimpleText( v.amount, v.font, v.x + self.PickupHistoryWide, ry + ( rh / 2 ), Color( 255, 255, 255, alpha ), TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER )
end
y = y + ( v.height + 16 )
tall = tall + v.height + 18
wide = math.max( wide, v.width + v.height + 24 )
if ( alpha == 0 ) then self.PickupHistory[ k ] = nil end
end
end
self.PickupHistoryTop = ( self.PickupHistoryTop * 5 + ( ScrH() * 0.75 - tall ) / 2 ) / 6
self.PickupHistoryWide = ( self.PickupHistoryWide * 5 + wide ) / 6
end

View File

@@ -0,0 +1,746 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
include( "shared.lua" )
include( "cl_scoreboard.lua" )
include( "cl_targetid.lua" )
include( "cl_hudpickup.lua" )
include( "cl_spawnmenu.lua" )
include( "cl_deathnotice.lua" )
include( "cl_pickteam.lua" )
include( "cl_voice.lua" )
--[[---------------------------------------------------------
Name: gamemode:Initialize()
Desc: Called immediately after starting the gamemode
-----------------------------------------------------------]]
function GM:Initialize()
GAMEMODE.ShowScoreboard = false
end
--[[---------------------------------------------------------
Name: gamemode:InitPostEntity()
Desc: Called as soon as all map entities have been spawned
-----------------------------------------------------------]]
function GM:InitPostEntity()
end
--[[---------------------------------------------------------
Name: gamemode:Think()
Desc: Called every frame
-----------------------------------------------------------]]
function GM:Think()
end
--[[---------------------------------------------------------
Name: gamemode:PlayerBindPress()
Desc: A player pressed a bound key - return true to override action
-----------------------------------------------------------]]
function GM:PlayerBindPress( pl, bind, down )
return false
end
--[[---------------------------------------------------------
Name: gamemode:HUDShouldDraw( name )
Desc: return true if we should draw the named element
-----------------------------------------------------------]]
function GM:HUDShouldDraw( name )
-- Allow the weapon to override this
local ply = LocalPlayer()
if ( IsValid( ply ) ) then
local wep = ply:GetActiveWeapon()
if ( IsValid( wep ) ) then
local fShouldDraw = wep.HUDShouldDraw
if ( isfunction( fShouldDraw ) ) then
local ret = fShouldDraw( wep, name )
if ( ret != nil ) then return ret end
end
end
end
return true
end
--[[---------------------------------------------------------
Name: gamemode:HUDPaint()
Desc: Use this section to paint your HUD
-----------------------------------------------------------]]
function GM:HUDPaint()
hook.Run( "HUDDrawTargetID" )
hook.Run( "HUDDrawPickupHistory" )
hook.Run( "DrawDeathNotice", 0.85, 0.04 )
end
--[[---------------------------------------------------------
Name: gamemode:HUDPaintBackground()
Desc: Same as HUDPaint except drawn before
-----------------------------------------------------------]]
function GM:HUDPaintBackground()
end
--[[---------------------------------------------------------
Name: gamemode:GUIMouseReleased( mousecode )
Desc: The mouse was double clicked
-----------------------------------------------------------]]
function GM:GUIMouseDoublePressed( mousecode, AimVector )
-- We don't capture double clicks by default,
-- We just treat them as regular presses
GAMEMODE:GUIMousePressed( mousecode, AimVector )
end
--[[---------------------------------------------------------
Name: gamemode:ShutDown( )
Desc: Called when the Lua system is about to shut down
-----------------------------------------------------------]]
function GM:ShutDown()
end
--[[---------------------------------------------------------
Name: gamemode:RenderScreenspaceEffects( )
Desc: Bloom etc should be drawn here (or using this hook)
-----------------------------------------------------------]]
function GM:RenderScreenspaceEffects()
end
--[[---------------------------------------------------------
Name: gamemode:GetTeamColor( ent )
Desc: Return the color for this ent's team
This is for chat and deathnotice text
-----------------------------------------------------------]]
function GM:GetTeamColor( ent )
local team = TEAM_UNASSIGNED
if ( ent.Team ) then team = ent:Team() end
return GAMEMODE:GetTeamNumColor( team )
end
--[[---------------------------------------------------------
Name: gamemode:GetTeamNumColor( num )
Desc: returns the colour for this team num
-----------------------------------------------------------]]
function GM:GetTeamNumColor( num )
return team.GetColor( num )
end
--[[---------------------------------------------------------
Name: gamemode:OnPlayerChat()
Process the player's chat.. return true for no default
-----------------------------------------------------------]]
function GM:OnPlayerChat( player, strText, bTeamOnly, bPlayerIsDead )
--
-- I've made this all look more complicated than it is. Here's the easy version
--
-- chat.AddText( player, color_white, ": ", strText )
--
local tab = {}
if ( bPlayerIsDead ) then
table.insert( tab, Color( 255, 30, 40 ) )
table.insert( tab, "*DEAD* " )
end
if ( bTeamOnly ) then
table.insert( tab, Color( 30, 160, 40 ) )
table.insert( tab, "(TEAM) " )
end
if ( IsValid( player ) ) then
table.insert( tab, player )
else
table.insert( tab, "Console" )
end
local filter_context = TEXT_FILTER_GAME_CONTENT
if ( bit.band( GetConVarNumber( "cl_chatfilters" ), 64 ) != 0 ) then filter_context = TEXT_FILTER_CHAT end
table.insert( tab, color_white )
table.insert( tab, ": " .. util.FilterText( strText, filter_context, IsValid( player ) and player or nil ) )
chat.AddText( unpack( tab ) )
return true
end
--[[---------------------------------------------------------
Name: gamemode:OnChatTab( str )
Desc: Tab is pressed when typing (Auto-complete names, IRC style)
-----------------------------------------------------------]]
function GM:OnChatTab( str )
str = string.TrimRight(str)
local LastWord
for word in string.gmatch( str, "[^ ]+" ) do
LastWord = word
end
if ( LastWord == nil ) then return str end
for k, v in ipairs( player.GetAll() ) do
local nickname = v:Nick()
if ( string.len( LastWord ) < string.len( nickname ) && string.find( string.lower( nickname ), string.lower( LastWord ), 0, true ) == 1 ) then
str = string.sub( str, 1, ( string.len( LastWord ) * -1 ) - 1 )
str = str .. nickname
return str
end
end
return str
end
--[[---------------------------------------------------------
Name: gamemode:StartChat( teamsay )
Desc: Start Chat.
If you want to display your chat shit different here's what you'd do:
In StartChat show your text box and return true to hide the default
Update the text in your box with the text passed to ChatTextChanged
Close and clear your text box when FinishChat is called.
Return true in ChatText to not show the default chat text
-----------------------------------------------------------]]
function GM:StartChat( teamsay )
return false
end
--[[---------------------------------------------------------
Name: gamemode:FinishChat()
-----------------------------------------------------------]]
function GM:FinishChat()
end
--[[---------------------------------------------------------
Name: gamemode:ChatTextChanged( text)
-----------------------------------------------------------]]
function GM:ChatTextChanged( text )
end
--[[---------------------------------------------------------
Name: ChatText
Allows override of the chat text
-----------------------------------------------------------]]
function GM:ChatText( playerindex, playername, text, filter )
if ( filter == "chat" ) then
Msg( playername, ": ", text, "\n" )
else
Msg( text, "\n" )
end
return false
end
--[[---------------------------------------------------------
Name: gamemode:PostProcessPermitted( str )
Desc: return true/false depending on whether this post process should be allowed
-----------------------------------------------------------]]
function GM:PostProcessPermitted( str )
return true
end
--[[---------------------------------------------------------
Name: gamemode:PostRenderVGUI( )
Desc: Called after VGUI has been rendered
-----------------------------------------------------------]]
function GM:PostRenderVGUI()
end
--[[---------------------------------------------------------
Name: gamemode:PreRender( )
Desc: Called before all rendering
Return true to NOT render this frame for some reason (danger!)
-----------------------------------------------------------]]
function GM:PreRender()
return false
end
--[[---------------------------------------------------------
Name: gamemode:PostRender( )
Desc: Called after all rendering
-----------------------------------------------------------]]
function GM:PostRender()
end
--[[---------------------------------------------------------
Name: gamemode:RenderScene( )
Desc: Render the scene
-----------------------------------------------------------]]
function GM:RenderScene( origin, angle, fov )
end
--[[---------------------------------------------------------
Name: CalcVehicleView
-----------------------------------------------------------]]
function GM:CalcVehicleView( Vehicle, ply, view )
if ( Vehicle.GetThirdPersonMode == nil || ply:GetViewEntity() != ply ) then
-- This shouldn't ever happen.
return
end
--
-- If we're not in third person mode - then get outa here stalker
--
if ( !Vehicle:GetThirdPersonMode() ) then return view end
-- Don't roll the camera
-- view.angles.roll = 0
local mn, mx = Vehicle:GetRenderBounds()
local radius = ( mn - mx ):Length()
local radius = radius + radius * Vehicle:GetCameraDistance()
-- Trace back from the original eye position, so we don't clip through walls/objects
local TargetOrigin = view.origin + ( view.angles:Forward() * -radius )
local WallOffset = 4
local tr = util.TraceHull( {
start = view.origin,
endpos = TargetOrigin,
filter = function( e )
local c = e:GetClass() -- Avoid contact with entities that can potentially be attached to the vehicle. Ideally, we should check if "e" is constrained to "Vehicle".
return !c:StartsWith( "prop_physics" ) &&!c:StartsWith( "prop_dynamic" ) && !c:StartsWith( "phys_bone_follower" ) && !c:StartsWith( "prop_ragdoll" ) && !e:IsVehicle() && !c:StartsWith( "gmod_" )
end,
mins = Vector( -WallOffset, -WallOffset, -WallOffset ),
maxs = Vector( WallOffset, WallOffset, WallOffset ),
} )
view.origin = tr.HitPos
view.drawviewer = true
--
-- If the trace hit something, put the camera there.
--
if ( tr.Hit && !tr.StartSolid) then
view.origin = view.origin + tr.HitNormal * WallOffset
end
return view
end
--[[---------------------------------------------------------
Name: CalcView
Allows override of the default view
-----------------------------------------------------------]]
function GM:CalcView( ply, origin, angles, fov, znear, zfar )
local Vehicle = ply:GetVehicle()
local Weapon = ply:GetActiveWeapon()
local view = {
["origin"] = origin,
["angles"] = angles,
["fov"] = fov,
["znear"] = znear,
["zfar"] = zfar,
["drawviewer"] = false,
}
--
-- Let the vehicle override the view and allows the vehicle view to be hooked
--
if ( IsValid( Vehicle ) ) then return hook.Run( "CalcVehicleView", Vehicle, ply, view ) end
--
-- Let drive possibly alter the view
--
if ( drive.CalcView( ply, view ) ) then return view end
--
-- Give the player manager a turn at altering the view
--
player_manager.RunClass( ply, "CalcView", view )
-- Give the active weapon a go at changing the view
if ( IsValid( Weapon ) ) then
local func = Weapon.CalcView
if ( func ) then
local origin, angles, fov = func( Weapon, ply, Vector( view.origin ), Angle( view.angles ), view.fov ) -- Note: Constructor to copy the object so the child function can't edit it.
view.origin, view.angles, view.fov = origin or view.origin, angles or view.angles, fov or view.fov
end
end
return view
end
--
-- If return true: Will draw the local player
-- If return false: Won't draw the local player
-- If return nil: Will carry out default action
--
function GM:ShouldDrawLocalPlayer( ply )
return player_manager.RunClass( ply, "ShouldDrawLocal" )
end
--[[---------------------------------------------------------
Name: gamemode:AdjustMouseSensitivity()
Desc: Allows you to adjust the mouse sensitivity.
The return is a fraction of the normal sensitivity (0.5 would be half as sensitive)
Return -1 to not override.
-----------------------------------------------------------]]
function GM:AdjustMouseSensitivity( fDefault )
local ply = LocalPlayer()
if ( !IsValid( ply ) ) then return -1 end
local wep = ply:GetActiveWeapon()
if ( wep && wep.AdjustMouseSensitivity ) then
return wep:AdjustMouseSensitivity()
end
return -1
end
--[[---------------------------------------------------------
Name: gamemode:ForceDermaSkin()
Desc: Return the name of skin this gamemode should use.
If nil is returned the skin will use default
-----------------------------------------------------------]]
function GM:ForceDermaSkin()
--return "example"
return nil
end
--[[---------------------------------------------------------
Name: gamemode:PostPlayerDraw()
Desc: The player has just been drawn.
-----------------------------------------------------------]]
function GM:PostPlayerDraw( ply )
end
--[[---------------------------------------------------------
Name: gamemode:PrePlayerDraw()
Desc: The player is just about to be drawn.
-----------------------------------------------------------]]
function GM:PrePlayerDraw( ply )
end
--[[---------------------------------------------------------
Name: gamemode:GetMotionBlurSettings()
Desc: Allows you to edit the motion blur values
-----------------------------------------------------------]]
function GM:GetMotionBlurValues( x, y, fwd, spin )
-- fwd = 0.5 + math.sin( CurTime() * 5 ) * 0.5
return x, y, fwd, spin
end
--[[---------------------------------------------------------
Name: gamemode:InputMouseApply()
Desc: Allows you to control how moving the mouse affects the view angles
-----------------------------------------------------------]]
function GM:InputMouseApply( cmd, x, y, angle )
--angle.roll = angle.roll + 1
--cmd:SetViewAngles( Ang )
--return true
end
--[[---------------------------------------------------------
Name: gamemode:OnAchievementAchieved()
-----------------------------------------------------------]]
function GM:OnAchievementAchieved( ply, achid )
chat.AddText( ply, Color( 230, 230, 230 ), " earned the achievement ", Color( 255, 200, 0 ), achievements.GetName( achid ) )
end
--[[---------------------------------------------------------
Name: gamemode:PreDrawSkyBox()
Desc: Called before drawing the skybox. Return true to not draw the skybox.
-----------------------------------------------------------]]
function GM:PreDrawSkyBox()
--return true
end
--[[---------------------------------------------------------
Name: gamemode:PostDrawSkyBox()
Desc: Called after drawing the skybox
-----------------------------------------------------------]]
function GM:PostDrawSkyBox()
end
--
-- Name: GM:PostDraw2DSkyBox
-- Desc: Called right after the 2D skybox has been drawn - allowing you to draw over it.
-- Arg1:
-- Ret1:
--
function GM:PostDraw2DSkyBox()
end
--[[---------------------------------------------------------
Name: gamemode:PreDrawOpaqueRenderables()
Desc: Called before drawing opaque entities
-----------------------------------------------------------]]
function GM:PreDrawOpaqueRenderables( bDrawingDepth, bDrawingSkybox )
-- return true
end
--[[---------------------------------------------------------
Name: gamemode:PreDrawOpaqueRenderables()
Desc: Called before drawing opaque entities
-----------------------------------------------------------]]
function GM:PostDrawOpaqueRenderables( bDrawingDepth, bDrawingSkybox )
end
--[[---------------------------------------------------------
Name: gamemode:PreDrawOpaqueRenderables()
Desc: Called before drawing opaque entities
-----------------------------------------------------------]]
function GM:PreDrawTranslucentRenderables( bDrawingDepth, bDrawingSkybox )
-- return true
end
--[[---------------------------------------------------------
Name: gamemode:PreDrawOpaqueRenderables()
Desc: Called before drawing opaque entities
-----------------------------------------------------------]]
function GM:PostDrawTranslucentRenderables( bDrawingDepth, bDrawingSkybox )
end
--[[---------------------------------------------------------
Name: gamemode:CalcViewModelView()
Desc: Called to set the view model's position
-----------------------------------------------------------]]
function GM:CalcViewModelView( Weapon, ViewModel, OldEyePos, OldEyeAng, EyePos, EyeAng )
if ( !IsValid( Weapon ) ) then return end
local vm_origin, vm_angles = EyePos, EyeAng
-- Controls the position of all viewmodels
local func = Weapon.GetViewModelPosition
if ( func ) then
local pos, ang = func( Weapon, EyePos*1, EyeAng*1 )
vm_origin = pos or vm_origin
vm_angles = ang or vm_angles
end
-- Controls the position of individual viewmodels
func = Weapon.CalcViewModelView
if ( func ) then
local pos, ang = func( Weapon, ViewModel, OldEyePos*1, OldEyeAng*1, EyePos*1, EyeAng*1 )
vm_origin = pos or vm_origin
vm_angles = ang or vm_angles
end
return vm_origin, vm_angles
end
--[[---------------------------------------------------------
Name: gamemode:PreDrawViewModel()
Desc: Called before drawing the view model
-----------------------------------------------------------]]
function GM:PreDrawViewModel( ViewModel, Player, Weapon )
if ( !IsValid( Weapon ) ) then return false end
player_manager.RunClass( Player, "PreDrawViewModel", ViewModel, Weapon )
if ( Weapon.PreDrawViewModel == nil ) then return false end
return Weapon:PreDrawViewModel( ViewModel, Weapon, Player )
end
--[[---------------------------------------------------------
Name: gamemode:PostDrawViewModel()
Desc: Called after drawing the view model
-----------------------------------------------------------]]
function GM:PostDrawViewModel( ViewModel, Player, Weapon )
if ( !IsValid( Weapon ) ) then return false end
if ( Weapon.UseHands || !Weapon:IsScripted() ) then
local hands = Player:GetHands()
if ( IsValid( hands ) && IsValid( hands:GetParent() ) ) then
if ( not hook.Call( "PreDrawPlayerHands", self, hands, ViewModel, Player, Weapon ) ) then
if ( Weapon.ViewModelFlip ) then render.CullMode( MATERIAL_CULLMODE_CW ) end
hands:DrawModel()
render.CullMode( MATERIAL_CULLMODE_CCW )
end
hook.Call( "PostDrawPlayerHands", self, hands, ViewModel, Player, Weapon )
end
end
player_manager.RunClass( Player, "PostDrawViewModel", ViewModel, Weapon )
if ( Weapon.PostDrawViewModel == nil ) then return false end
return Weapon:PostDrawViewModel( ViewModel, Weapon, Player )
end
--[[---------------------------------------------------------
Name: gamemode:DrawPhysgunBeam()
Desc: Return false to override completely
-----------------------------------------------------------]]
function GM:DrawPhysgunBeam( ply, weapon, bOn, target, boneid, pos )
-- Do nothing
return true
end
--[[---------------------------------------------------------
Name: gamemode:NetworkEntityCreated()
Desc: Entity is created over the network
-----------------------------------------------------------]]
function GM:NetworkEntityCreated( ent )
end
--[[---------------------------------------------------------
Name: gamemode:CreateMove( command )
Desc: Allows the client to change the move commands
before it's send to the server
-----------------------------------------------------------]]
function GM:CreateMove( cmd )
if ( drive.CreateMove( cmd ) ) then return true end
if ( player_manager.RunClass( LocalPlayer(), "CreateMove", cmd ) ) then return true end
end
--[[---------------------------------------------------------
Name: gamemode:PreventScreenClicks()
Desc: The player is hovering over a ScreenClickable world
-----------------------------------------------------------]]
function GM:PreventScreenClicks( cmd )
--
-- Returning true in this hook will prevent screen clicking sending IN_ATTACK
-- commands to the weapons. We want to do this in the properties system, so
-- that you don't fire guns when opening the properties menu. Holla!
--
return false
end
--[[---------------------------------------------------------
Name: gamemode:GUIMousePressed( mousecode )
Desc: The mouse has been pressed on the game screen
-----------------------------------------------------------]]
function GM:GUIMousePressed( mousecode, AimVector )
end
--[[---------------------------------------------------------
Name: gamemode:GUIMouseReleased( mousecode )
Desc: The mouse has been released on the game screen
-----------------------------------------------------------]]
function GM:GUIMouseReleased( mousecode, AimVector )
end
--[[---------------------------------------------------------
Player class has been changed
-----------------------------------------------------------]]
function GM:PlayerClassChanged( ply, newID )
-- No class is set
if ( newID < 1 ) then return end
-- Invalid class ID?
local classname = util.NetworkIDToString( newID )
if ( !classname ) then return end
-- Initialize the class on client
player_manager.SetPlayerClass( ply, classname )
end
function GM:PreDrawHUD()
end
function GM:PostDrawHUD()
end
function GM:DrawOverlay()
end
function GM:DrawMonitors()
end
function GM:PreDrawEffects()
end
function GM:PostDrawEffects()
end
function GM:PreDrawHalos()
end
function GM:CloseDermaMenus()
end
function GM:CreateClientsideRagdoll( entity, ragdoll )
end
function GM:VehicleMove( ply, vehicle, mv )
end

View File

@@ -0,0 +1,75 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
--[[---------------------------------------------------------
Name: gamemode:ShowTeam()
Desc:
-----------------------------------------------------------]]
function GM:ShowTeam()
if ( IsValid( self.TeamSelectFrame ) ) then return end
-- Simple team selection box
self.TeamSelectFrame = vgui.Create( "DFrame" )
self.TeamSelectFrame:SetTitle( "Pick Team" )
local AllTeams = team.GetAllTeams()
local y = 30
for ID, TeamInfo in pairs ( AllTeams ) do
if ( ID != TEAM_CONNECTING && ID != TEAM_UNASSIGNED ) then
local Team = vgui.Create( "DButton", self.TeamSelectFrame )
function Team.DoClick() self:HideTeam() RunConsoleCommand( "changeteam", ID ) end
Team:SetPos( 10, y )
Team:SetSize( 130, 20 )
Team:SetText( TeamInfo.Name )
if ( IsValid( LocalPlayer() ) && LocalPlayer():Team() == ID ) then
Team:SetEnabled( false )
end
y = y + 30
end
end
if ( GAMEMODE.AllowAutoTeam ) then
local Team = vgui.Create( "DButton", self.TeamSelectFrame )
function Team.DoClick() self:HideTeam() RunConsoleCommand( "autoteam" ) end
Team:SetPos( 10, y )
Team:SetSize( 130, 20 )
Team:SetText( "Auto" )
y = y + 30
end
self.TeamSelectFrame:SetSize( 150, y )
self.TeamSelectFrame:Center()
self.TeamSelectFrame:MakePopup()
self.TeamSelectFrame:SetKeyboardInputEnabled( false )
end
--[[---------------------------------------------------------
Name: gamemode:HideTeam()
Desc:
-----------------------------------------------------------]]
function GM:HideTeam()
if ( IsValid(self.TeamSelectFrame) ) then
self.TeamSelectFrame:Remove()
self.TeamSelectFrame = nil
end
end

View File

@@ -0,0 +1,305 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
surface.CreateFont( "ScoreboardDefault", {
font = "Helvetica",
size = 22,
weight = 800
} )
surface.CreateFont( "ScoreboardDefaultTitle", {
font = "Helvetica",
size = 32,
weight = 800
} )
--
-- This defines a new panel type for the player row. The player row is given a player
-- and then from that point on it pretty much looks after itself. It updates player info
-- in the think function, and removes itself when the player leaves the server.
--
local PLAYER_LINE = {
Init = function( self )
self.AvatarButton = self:Add( "DButton" )
self.AvatarButton:Dock( LEFT )
self.AvatarButton:SetSize( 32, 32 )
self.AvatarButton.DoClick = function() self.Player:ShowProfile() end
self.Avatar = vgui.Create( "AvatarImage", self.AvatarButton )
self.Avatar:SetSize( 32, 32 )
self.Avatar:SetMouseInputEnabled( false )
self.Name = self:Add( "DLabel" )
self.Name:Dock( FILL )
self.Name:SetFont( "ScoreboardDefault" )
self.Name:SetTextColor( Color( 93, 93, 93 ) )
self.Name:DockMargin( 8, 0, 0, 0 )
self.Mute = self:Add( "DImageButton" )
self.Mute:SetSize( 32, 32 )
self.Mute:Dock( RIGHT )
self.Ping = self:Add( "DLabel" )
self.Ping:Dock( RIGHT )
self.Ping:SetWidth( 50 )
self.Ping:SetFont( "ScoreboardDefault" )
self.Ping:SetTextColor( Color( 93, 93, 93 ) )
self.Ping:SetContentAlignment( 5 )
self.Deaths = self:Add( "DLabel" )
self.Deaths:Dock( RIGHT )
self.Deaths:SetWidth( 50 )
self.Deaths:SetFont( "ScoreboardDefault" )
self.Deaths:SetTextColor( Color( 93, 93, 93 ) )
self.Deaths:SetContentAlignment( 5 )
self.Kills = self:Add( "DLabel" )
self.Kills:Dock( RIGHT )
self.Kills:SetWidth( 50 )
self.Kills:SetFont( "ScoreboardDefault" )
self.Kills:SetTextColor( Color( 93, 93, 93 ) )
self.Kills:SetContentAlignment( 5 )
self:Dock( TOP )
self:DockPadding( 3, 3, 3, 3 )
self:SetHeight( 32 + 3 * 2 )
self:DockMargin( 2, 0, 2, 2 )
end,
Setup = function( self, pl )
self.Player = pl
self.Avatar:SetPlayer( pl )
self:Think( self )
--local friend = self.Player:GetFriendStatus()
--MsgN( pl, " Friend: ", friend )
end,
Think = function( self )
if ( !IsValid( self.Player ) ) then
self:SetZPos( 9999 ) -- Causes a rebuild
self:Remove()
return
end
if ( self.PName == nil || self.PName != self.Player:Nick() ) then
self.PName = self.Player:Nick()
self.Name:SetText( self.PName )
end
if ( self.NumKills == nil || self.NumKills != self.Player:Frags() ) then
self.NumKills = self.Player:Frags()
self.Kills:SetText( self.NumKills )
end
if ( self.NumDeaths == nil || self.NumDeaths != self.Player:Deaths() ) then
self.NumDeaths = self.Player:Deaths()
self.Deaths:SetText( self.NumDeaths )
end
if ( self.NumPing == nil || self.NumPing != self.Player:Ping() ) then
self.NumPing = self.Player:Ping()
self.Ping:SetText( self.NumPing )
end
--
-- Change the icon of the mute button based on state
--
if ( self.Muted == nil || self.Muted != self.Player:IsMuted() ) then
self.Muted = self.Player:IsMuted()
if ( self.Muted ) then
self.Mute:SetImage( "icon32/muted.png" )
else
self.Mute:SetImage( "icon32/unmuted.png" )
end
self.Mute.DoClick = function( s ) self.Player:SetMuted( !self.Muted ) end
self.Mute.OnMouseWheeled = function( s, delta )
self.Player:SetVoiceVolumeScale( self.Player:GetVoiceVolumeScale() + ( delta / 100 * 5 ) )
s.LastTick = CurTime()
end
self.Mute.PaintOver = function( s, w, h )
if ( !IsValid( self.Player ) ) then return end
local a = 255 - math.Clamp( CurTime() - ( s.LastTick or 0 ), 0, 3 ) * 255
if ( a <= 0 ) then return end
draw.RoundedBox( 4, 0, 0, w, h, Color( 0, 0, 0, a * 0.75 ) )
draw.SimpleText( math.ceil( self.Player:GetVoiceVolumeScale() * 100 ) .. "%", "DermaDefaultBold", w / 2, h / 2, Color( 255, 255, 255, a ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER )
end
end
--
-- Connecting players go at the very bottom
--
if ( self.Player:Team() == TEAM_CONNECTING ) then
self:SetZPos( 2000 + self.Player:EntIndex() )
return
end
--
-- This is what sorts the list. The panels are docked in the z order,
-- so if we set the z order according to kills they'll be ordered that way!
-- Careful though, it's a signed short internally, so needs to range between -32,768k and +32,767
--
self:SetZPos( ( self.NumKills * -50 ) + self.NumDeaths + self.Player:EntIndex() )
end,
Paint = function( self, w, h )
if ( !IsValid( self.Player ) ) then
return
end
--
-- We draw our background a different colour based on the status of the player
--
if ( self.Player:Team() == TEAM_CONNECTING ) then
draw.RoundedBox( 4, 0, 0, w, h, Color( 200, 200, 200, 200 ) )
return
end
if ( !self.Player:Alive() ) then
draw.RoundedBox( 4, 0, 0, w, h, Color( 230, 200, 200, 255 ) )
return
end
if ( self.Player:IsAdmin() ) then
draw.RoundedBox( 4, 0, 0, w, h, Color( 230, 255, 230, 255 ) )
return
end
draw.RoundedBox( 4, 0, 0, w, h, Color( 230, 230, 230, 255 ) )
end
}
--
-- Convert it from a normal table into a Panel Table based on DPanel
--
PLAYER_LINE = vgui.RegisterTable( PLAYER_LINE, "DPanel" )
--
-- Here we define a new panel table for the scoreboard. It basically consists
-- of a header and a scrollpanel - into which the player lines are placed.
--
local SCORE_BOARD = {
Init = function( self )
self.Header = self:Add( "Panel" )
self.Header:Dock( TOP )
self.Header:SetHeight( 100 )
self.Name = self.Header:Add( "DLabel" )
self.Name:SetFont( "ScoreboardDefaultTitle" )
self.Name:SetTextColor( color_white )
self.Name:Dock( TOP )
self.Name:SetHeight( 40 )
self.Name:SetContentAlignment( 5 )
self.Name:SetExpensiveShadow( 2, Color( 0, 0, 0, 200 ) )
--self.NumPlayers = self.Header:Add( "DLabel" )
--self.NumPlayers:SetFont( "ScoreboardDefault" )
--self.NumPlayers:SetTextColor( color_white )
--self.NumPlayers:SetPos( 0, 100 - 30 )
--self.NumPlayers:SetSize( 300, 30 )
--self.NumPlayers:SetContentAlignment( 4 )
self.Scores = self:Add( "DScrollPanel" )
self.Scores:Dock( FILL )
end,
PerformLayout = function( self )
self:SetSize( 700, ScrH() - 200 )
self:SetPos( ScrW() / 2 - 350, 100 )
end,
Paint = function( self, w, h )
--draw.RoundedBox( 4, 0, 0, w, h, Color( 0, 0, 0, 200 ) )
end,
Think = function( self, w, h )
self.Name:SetText( GetHostName() )
--
-- Loop through each player, and if one doesn't have a score entry - create it.
--
for id, pl in ipairs( player.GetAll() ) do
if ( IsValid( pl.ScoreEntry ) ) then continue end
pl.ScoreEntry = vgui.CreateFromTable( PLAYER_LINE, pl.ScoreEntry )
pl.ScoreEntry:Setup( pl )
self.Scores:AddItem( pl.ScoreEntry )
end
end
}
SCORE_BOARD = vgui.RegisterTable( SCORE_BOARD, "EditablePanel" )
--[[---------------------------------------------------------
Name: gamemode:ScoreboardShow( )
Desc: Sets the scoreboard to visible
-----------------------------------------------------------]]
function GM:ScoreboardShow()
if ( !IsValid( g_Scoreboard ) ) then
g_Scoreboard = vgui.CreateFromTable( SCORE_BOARD )
end
if ( IsValid( g_Scoreboard ) ) then
g_Scoreboard:Show()
g_Scoreboard:MakePopup()
g_Scoreboard:SetKeyboardInputEnabled( false )
end
end
--[[---------------------------------------------------------
Name: gamemode:ScoreboardHide( )
Desc: Hides the scoreboard
-----------------------------------------------------------]]
function GM:ScoreboardHide()
if ( IsValid( g_Scoreboard ) ) then
g_Scoreboard:Hide()
end
end
--[[---------------------------------------------------------
Name: gamemode:HUDDrawScoreBoard( )
Desc: If you prefer to draw your scoreboard the stupid way (without vgui)
-----------------------------------------------------------]]
function GM:HUDDrawScoreBoard()
end

View File

@@ -0,0 +1,46 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
--[[---------------------------------------------------------
Spawn Menu
-----------------------------------------------------------]]
function GM:OnSpawnMenuOpen()
end
function GM:OnSpawnMenuClose()
end
concommand.Add( "+menu", function()
hook.Run( "OnSpawnMenuOpen" )
end, nil, "Opens the spawnmenu", FCVAR_DONTRECORD )
concommand.Add( "-menu", function()
if ( input.IsKeyTrapping() ) then return end
hook.Run( "OnSpawnMenuClose" )
end, nil, "Closes the spawnmenu", FCVAR_DONTRECORD )
--[[---------------------------------------------------------
Context Menu
-----------------------------------------------------------]]
function GM:OnContextMenuOpen()
end
function GM:OnContextMenuClose()
end
concommand.Add( "+menu_context", function()
hook.Run( "OnContextMenuOpen" )
end, nil, "Opens the context menu", FCVAR_DONTRECORD )
concommand.Add( "-menu_context", function()
if ( input.IsKeyTrapping() ) then return end
hook.Run( "OnContextMenuClose" )
end, nil, "Closes the context menu", FCVAR_DONTRECORD )

View File

@@ -0,0 +1,70 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
--[[---------------------------------------------------------
Name: gamemode:HUDDrawTargetID( )
Desc: Draw the target id (the name of the player you're currently looking at)
-----------------------------------------------------------]]
function GM:HUDDrawTargetID()
local tr = util.GetPlayerTrace( LocalPlayer() )
local trace = util.TraceLine( tr )
if ( !trace.Hit ) then return end
if ( !trace.HitNonWorld ) then return end
local text = "ERROR"
local font = "TargetID"
if ( trace.Entity:IsPlayer() ) then
text = trace.Entity:Nick()
else
--text = trace.Entity:GetClass()
return
end
surface.SetFont( font )
local w, h = surface.GetTextSize( text )
local MouseX, MouseY = input.GetCursorPos()
if ( MouseX == 0 && MouseY == 0 || !vgui.CursorVisible() ) then
MouseX = ScrW() / 2
MouseY = ScrH() / 2
end
local x = MouseX
local y = MouseY
x = x - w / 2
y = y + 30
-- The fonts internal drop shadow looks lousy with AA on
draw.SimpleText( text, font, x + 1, y + 1, Color( 0, 0, 0, 120 ) )
draw.SimpleText( text, font, x + 2, y + 2, Color( 0, 0, 0, 50 ) )
draw.SimpleText( text, font, x, y, self:GetTeamColor( trace.Entity ) )
y = y + h + 5
-- Draw the health
text = trace.Entity:Health() .. "%"
font = "TargetIDSmall"
surface.SetFont( font )
w, h = surface.GetTextSize( text )
x = MouseX - w / 2
draw.SimpleText( text, font, x + 1, y + 1, Color( 0, 0, 0, 120 ) )
draw.SimpleText( text, font, x + 2, y + 2, Color( 0, 0, 0, 50 ) )
draw.SimpleText( text, font, x, y, self:GetTeamColor( trace.Entity ) )
end

View File

@@ -0,0 +1,154 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PANEL = {}
local PlayerVoicePanels = {}
function PANEL:Init()
self.LabelName = vgui.Create( "DLabel", self )
self.LabelName:SetFont( "GModNotify" )
self.LabelName:Dock( FILL )
self.LabelName:DockMargin( 8, 0, 0, 0 )
self.LabelName:SetTextColor( color_white )
self.Avatar = vgui.Create( "AvatarImage", self )
self.Avatar:Dock( LEFT )
self.Avatar:SetSize( 32, 32 )
self.Color = color_transparent
self:SetSize( 250, 32 + 8 )
self:DockPadding( 4, 4, 4, 4 )
self:DockMargin( 2, 2, 2, 2 )
self:Dock( BOTTOM )
end
function PANEL:Setup( ply )
self.ply = ply
self.LabelName:SetText( ply:Nick() )
self.Avatar:SetPlayer( ply )
self.Color = team.GetColor( ply:Team() )
self:InvalidateLayout()
end
function PANEL:Paint( w, h )
if ( !IsValid( self.ply ) ) then return end
draw.RoundedBox( 4, 0, 0, w, h, Color( 0, self.ply:VoiceVolume() * 255, 0, 240 ) )
end
function PANEL:Think()
if ( IsValid( self.ply ) ) then
self.LabelName:SetText( self.ply:Nick() )
end
if ( self.fadeAnim ) then
self.fadeAnim:Run()
end
end
function PANEL:FadeOut( anim, delta, data )
if ( anim.Finished ) then
if ( IsValid( PlayerVoicePanels[ self.ply ] ) ) then
PlayerVoicePanels[ self.ply ]:Remove()
PlayerVoicePanels[ self.ply ] = nil
return
end
return end
self:SetAlpha( 255 - ( 255 * delta ) )
end
derma.DefineControl( "VoiceNotify", "", PANEL, "DPanel" )
function GM:PlayerStartVoice( ply )
if ( !IsValid( g_VoicePanelList ) ) then return end
-- There'd be an exta one if voice_loopback is on, so remove it.
GAMEMODE:PlayerEndVoice( ply )
if ( IsValid( PlayerVoicePanels[ ply ] ) ) then
if ( PlayerVoicePanels[ ply ].fadeAnim ) then
PlayerVoicePanels[ ply ].fadeAnim:Stop()
PlayerVoicePanels[ ply ].fadeAnim = nil
end
PlayerVoicePanels[ ply ]:SetAlpha( 255 )
return
end
if ( !IsValid( ply ) ) then return end
local pnl = g_VoicePanelList:Add( "VoiceNotify" )
pnl:Setup( ply )
PlayerVoicePanels[ ply ] = pnl
end
local function VoiceClean()
for k, v in pairs( PlayerVoicePanels ) do
if ( !IsValid( k ) ) then
GAMEMODE:PlayerEndVoice( k )
end
end
end
timer.Create( "VoiceClean", 10, 0, VoiceClean )
function GM:PlayerEndVoice( ply )
if ( IsValid( PlayerVoicePanels[ ply ] ) ) then
if ( PlayerVoicePanels[ ply ].fadeAnim ) then return end
PlayerVoicePanels[ ply ].fadeAnim = Derma_Anim( "FadeOut", PlayerVoicePanels[ ply ], PlayerVoicePanels[ ply ].FadeOut )
PlayerVoicePanels[ ply ].fadeAnim:Start( 2 )
end
end
local function CreateVoiceVGUI()
g_VoicePanelList = vgui.Create( "DPanel" )
g_VoicePanelList:ParentToHUD()
g_VoicePanelList:SetPos( ScrW() - 300, 100 )
g_VoicePanelList:SetSize( 250, ScrH() - 200 )
g_VoicePanelList:SetPaintBackground( false )
end
hook.Add( "InitPostEntity", "CreateVoiceVGUI", CreateVoiceVGUI )

View File

@@ -0,0 +1,46 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
--[[---------------------------------------------------------
Name: gamemode:GravGunPunt()
Desc: We're about to punt an entity (primary fire).
Return true if we're allowed to.
-----------------------------------------------------------]]
function GM:GravGunPunt( ply, ent )
return true
end
--[[---------------------------------------------------------
Name: gamemode:GravGunPickupAllowed()
Desc: Return true if we're allowed to pickup entity
-----------------------------------------------------------]]
function GM:GravGunPickupAllowed( ply, ent )
return true
end
if ( SERVER ) then
--[[---------------------------------------------------------
Name: gamemode:GravGunOnPickedUp()
Desc: The entity has been picked up
-----------------------------------------------------------]]
function GM:GravGunOnPickedUp( ply, ent )
end
--[[---------------------------------------------------------
Name: gamemode:GravGunOnDropped()
Desc: The entity has been dropped
-----------------------------------------------------------]]
function GM:GravGunOnDropped( ply, ent )
end
end

View File

@@ -0,0 +1,190 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
include( 'shared.lua' )
include( 'player.lua' )
include( 'npc.lua' )
include( 'variable_edit.lua' )
--[[---------------------------------------------------------
Name: gamemode:Initialize()
Desc: Called immediately after starting the gamemode
-----------------------------------------------------------]]
function GM:Initialize()
end
--[[---------------------------------------------------------
Name: gamemode:InitPostEntity()
Desc: Called as soon as all map entities have been spawned
-----------------------------------------------------------]]
function GM:InitPostEntity()
end
--[[---------------------------------------------------------
Name: gamemode:Think()
Desc: Called every frame
-----------------------------------------------------------]]
function GM:Think()
end
--[[---------------------------------------------------------
Name: gamemode:ShutDown()
Desc: Called when the Lua system is about to shut down
-----------------------------------------------------------]]
function GM:ShutDown()
end
--[[---------------------------------------------------------
Name: gamemode:DoPlayerDeath( )
Desc: Carries out actions when the player dies
-----------------------------------------------------------]]
function GM:DoPlayerDeath( ply, attacker, dmginfo )
if ( !dmginfo:IsDamageType( DMG_REMOVENORAGDOLL ) ) then
ply:CreateRagdoll()
end
ply:AddDeaths( 1 )
if ( attacker:IsValid() && attacker:IsPlayer() ) then
if ( attacker == ply ) then
attacker:AddFrags( -1 )
else
attacker:AddFrags( 1 )
end
end
end
--[[---------------------------------------------------------
Name: gamemode:PlayerShouldTakeDamage
Return true if this player should take damage from this attacker
-----------------------------------------------------------]]
function GM:PlayerShouldTakeDamage( ply, attacker )
return true
end
--[[---------------------------------------------------------
Name: gamemode:EntityTakeDamage( ent, info )
Desc: The entity has received damage
-----------------------------------------------------------]]
function GM:EntityTakeDamage( ent, info )
end
--[[---------------------------------------------------------
Name: gamemode:PlayerHurt( )
Desc: Called when a player is hurt.
-----------------------------------------------------------]]
function GM:PlayerHurt( player, attacker, healthleft, healthtaken )
end
--[[---------------------------------------------------------
Name: gamemode:CreateEntityRagdoll( entity, ragdoll )
Desc: A ragdoll of an entity has been created
-----------------------------------------------------------]]
function GM:CreateEntityRagdoll( entity, ragdoll )
end
-- Set the ServerName every 30 seconds in case it changes..
-- This is for backwards compatibility only - client can now use GetHostName()
local function HostnameThink()
SetGlobalString( "ServerName", GetHostName() )
end
timer.Create( "HostnameThink", 30, 0, HostnameThink )
--[[---------------------------------------------------------
Show the default team selection screen
-----------------------------------------------------------]]
function GM:ShowTeam( ply )
if ( !GAMEMODE.TeamBased ) then return end
local TimeBetweenSwitches = GAMEMODE.SecondsBetweenTeamSwitches or 10
if ( ply.LastTeamSwitch && RealTime() - ply.LastTeamSwitch < TimeBetweenSwitches ) then
ply.LastTeamSwitch = ply.LastTeamSwitch + 1
ply:ChatPrint( Format( "Please wait %i more seconds before trying to change team again", ( TimeBetweenSwitches - ( RealTime() - ply.LastTeamSwitch ) ) + 1 ) )
return
end
-- For clientside see cl_pickteam.lua
ply:SendLua( "GAMEMODE:ShowTeam()" )
end
--
-- CheckPassword( steamid, networkid, server_password, password, name )
--
-- Called every time a non-localhost player joins the server. steamid is their 64bit
-- steamid. Return false and a reason to reject their join. Return true to allow
-- them to join.
--
function GM:CheckPassword( steamid, networkid, server_password, password, name )
-- The server has sv_password set
if ( server_password != "" ) then
-- The joining clients password doesn't match sv_password
if ( server_password != password ) then
return false
end
end
--
-- Returning true means they're allowed to join the server
--
return true
end
--[[---------------------------------------------------------
Name: gamemode:FinishMove( player, movedata )
-----------------------------------------------------------]]
function GM:VehicleMove( ply, vehicle, mv )
--
-- On duck toggle third person view
--
if ( mv:KeyPressed( IN_DUCK ) && vehicle.SetThirdPersonMode ) then
vehicle:SetThirdPersonMode( !vehicle:GetThirdPersonMode() )
end
--
-- Adjust the camera distance with the mouse wheel
--
local iWheel = ply:GetCurrentCommand():GetMouseWheel()
if ( iWheel != 0 && vehicle.SetCameraDistance ) then
-- The distance is a multiplier
-- Actual camera distance = ( renderradius + renderradius * dist )
-- so -1 will be zero.. clamp it there.
local newdist = math.Clamp( vehicle:GetCameraDistance() - iWheel * 0.03 * ( 1.1 + vehicle:GetCameraDistance() ), -1, 10 )
vehicle:SetCameraDistance( newdist )
end
end
--[[---------------------------------------------------------
Name: gamemode:PreUndo( undo )
-----------------------------------------------------------]]
function GM:PreUndo( undo )
return true
end
--[[---------------------------------------------------------
Name: gamemode:PreUndo( undo )
-----------------------------------------------------------]]
function GM:PostUndo( undo, count )
end

View File

@@ -0,0 +1,211 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
-- Backwards compatibility with addons
util.AddNetworkString( "PlayerKilledNPC" )
util.AddNetworkString( "NPCKilledNPC" )
util.AddNetworkString( "PlayerKilled" )
util.AddNetworkString( "PlayerKilledSelf" )
util.AddNetworkString( "PlayerKilledByPlayer" )
-- New way
util.AddNetworkString( "DeathNoticeEvent" )
DEATH_NOTICE_FRIENDLY_VICTIM = 1
DEATH_NOTICE_FRIENDLY_ATTACKER = 2
--DEATH_NOTICE_HEADSHOT = 4
--DEATH_NOTICE_PENETRATION = 8
function GM:SendDeathNotice( attacker, inflictor, victim, flags )
net.Start( "DeathNoticeEvent" )
if ( !attacker ) then
net.WriteUInt( 0, 2 )
elseif ( isstring( attacker ) ) then
net.WriteUInt( 1, 2 )
net.WriteString( attacker )
elseif ( IsValid( attacker ) ) then
net.WriteUInt( 2, 2 )
net.WriteEntity( attacker )
end
net.WriteString( inflictor )
if ( !victim ) then
net.WriteUInt( 0, 2 )
elseif ( isstring( victim ) ) then
net.WriteUInt( 1, 2 )
net.WriteString( victim )
elseif ( IsValid( victim ) ) then
net.WriteUInt( 2, 2 )
net.WriteEntity( victim )
end
net.WriteUInt( flags, 8 )
net.Broadcast()
end
function GM:GetDeathNoticeEntityName( ent )
-- Some specific HL2 NPCs, just for fun
-- TODO: Localization strings?
if ( ent:GetClass() == "npc_citizen" ) then
if ( ent:GetName() == "griggs" ) then return "Griggs" end
if ( ent:GetName() == "sheckley" ) then return "Sheckley" end
if ( ent:GetName() == "tobias" ) then return "Laszlo" end
if ( ent:GetName() == "stanley" ) then return "Sandy" end
end
-- Custom vehicle and NPC names from spawnmenu
if ( ent:IsVehicle() and ent.VehicleTable and ent.VehicleTable.Name ) then
return ent.VehicleTable.Name
end
if ( ent:IsNPC() and ent.NPCTable and ent.NPCTable.Name ) then
return ent.NPCTable.Name
end
-- Map spawned Odessa or Rebels, etc..
for unique_class, NPC in pairs( list.Get( "NPC" ) ) do
if ( unique_class == NPC.Class or ent:GetClass() != NPC.Class ) then continue end
local allGood = true
if ( NPC.Model and ent:GetModel() != NPC.Model ) then
allGood = false
end
if ( NPC.Skin and ent:GetSkin() != NPC.Skin ) then
allGood = false
end
-- For Rebels, etc.
if ( NPC.KeyValues ) then
for k, v in pairs( NPC.KeyValues ) do
local kL = k:lower()
if ( kL != "squadname" and kL != "numgrenades" and ent:GetInternalVariable( k ) != v ) then
allGood = false
break
end
end
-- They get unset often :(
--if ( NPC.SpawnFlags and ent:HasSpawnFlags( NPC.SpawnFlags ) ) then allGood = false end
end
-- Medics, ew..
if ( unique_class == "Medic" and !ent:HasSpawnFlags( SF_CITIZEN_MEDIC ) ) then allGood = false end
if ( unique_class == "Rebel" and ent:HasSpawnFlags( SF_CITIZEN_MEDIC ) ) then allGood = false end
if ( allGood ) then return NPC.Name end
end
-- Unfortunately the code above still doesn't work for Antlion Workers, because they change their classname..
if ( ent:GetClass() == "npc_antlion" and ent:GetModel() == "models/antlion_worker.mdl" ) then
return list.Get( "NPC" )[ "npc_antlion_worker" ].Name
end
-- Fallback to old behavior
return "#" .. ent:GetClass()
end
--[[---------------------------------------------------------
Name: gamemode:OnNPCKilled( entity, attacker, inflictor )
Desc: The NPC has died
-----------------------------------------------------------]]
function GM:OnNPCKilled( ent, attacker, inflictor )
-- Don't spam the killfeed with scripted stuff
if ( ent:GetClass() == "npc_bullseye" or ent:GetClass() == "npc_launcher" ) then return end
-- If killed by trigger_hurt, act as if NPC killed itself
if ( IsValid( attacker ) and attacker:GetClass() == "trigger_hurt" ) then attacker = ent end
-- NPC got run over..
if ( IsValid( attacker ) and attacker:IsVehicle() and IsValid( attacker:GetDriver() ) ) then
attacker = attacker:GetDriver()
end
if ( !IsValid( inflictor ) and IsValid( attacker ) ) then
inflictor = attacker
end
-- Convert the inflictor to the weapon that they're holding if we can.
if ( IsValid( inflictor ) and attacker == inflictor and ( inflictor:IsPlayer() or inflictor:IsNPC() ) ) then
inflictor = inflictor:GetActiveWeapon()
if ( !IsValid( attacker ) ) then inflictor = attacker end
end
local InflictorClass = "worldspawn"
local AttackerClass = game.GetWorld()
if ( IsValid( inflictor ) ) then InflictorClass = inflictor:GetClass() end
if ( IsValid( attacker ) ) then
AttackerClass = attacker
-- If there is no valid inflictor, use the attacker (i.e. manhacks)
if ( !IsValid( inflictor ) ) then InflictorClass = attacker:GetClass() end
if ( attacker:IsPlayer() ) then
local flags = 0
if ( ent:IsNPC() and ent:Disposition( attacker ) != D_HT ) then flags = flags + DEATH_NOTICE_FRIENDLY_VICTIM end
self:SendDeathNotice( attacker, InflictorClass, self:GetDeathNoticeEntityName( ent ), flags )
return
end
end
-- Floor turret got knocked over
if ( ent:GetClass() == "npc_turret_floor" ) then AttackerClass = ent end
-- It was NPC suicide..
if ( ent == AttackerClass ) then InflictorClass = "suicide" end
local flags = 0
if ( IsValid( Entity( 1 ) ) and ent:IsNPC() and ent:Disposition( Entity( 1 ) ) == D_LI ) then flags = flags + DEATH_NOTICE_FRIENDLY_VICTIM end
if ( IsValid( Entity( 1 ) ) and AttackerClass:IsNPC() and AttackerClass:Disposition( Entity( 1 ) ) == D_LI ) then flags = flags + DEATH_NOTICE_FRIENDLY_ATTACKER end
self:SendDeathNotice( self:GetDeathNoticeEntityName( AttackerClass ), InflictorClass, self:GetDeathNoticeEntityName( ent ), flags )
end
--[[---------------------------------------------------------
Name: gamemode:ScaleNPCDamage( ply, hitgroup, dmginfo )
Desc: Scale the damage based on being shot in a hitbox
-----------------------------------------------------------]]
function GM:ScaleNPCDamage( npc, hitgroup, dmginfo )
-- More damage if we're shot in the head
if ( hitgroup == HITGROUP_HEAD ) then
dmginfo:ScaleDamage( 2 )
end
-- Less damage if we're shot in the arms or legs
if ( hitgroup == HITGROUP_LEFTARM or
hitgroup == HITGROUP_RIGHTARM or
hitgroup == HITGROUP_LEFTLEG or
hitgroup == HITGROUP_RIGHTLEG or
hitgroup == HITGROUP_GEAR ) then
dmginfo:ScaleDamage( 0.25 )
end
end

View File

@@ -0,0 +1,223 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local meta = FindMetaTable( "Player" )
if ( !meta ) then return end
-- In this file we're adding functions to the player meta table.
-- This means you'll be able to call functions here straight from the player object
-- You can even override already existing functions.
--[[---------------------------------------------------------
Name: AddFrozenPhysicsObject
Desc: For the Physgun, adds a frozen object to the player's list
-----------------------------------------------------------]]
function meta:AddFrozenPhysicsObject( ent, phys )
-- Get the player's table
local tab = self:GetTable()
-- Make sure the physics objects table exists
tab.FrozenPhysicsObjects = tab.FrozenPhysicsObjects or {}
-- Make a new table that contains the info
local entry = {}
entry.ent = ent
entry.phys = phys
table.insert( tab.FrozenPhysicsObjects, entry )
gamemode.Call( "PlayerFrozeObject", self, ent, phys )
end
local function PlayerUnfreezeObject( ply, ent, object )
-- Not frozen!
if ( object:IsMoveable() ) then return 0 end
-- Unfreezable means it can't be frozen or unfrozen.
-- This prevents the player unfreezing the gmod_anchor entity.
if ( ent:GetUnFreezable() ) then return 0 end
-- NOTE: IF YOU'RE MAKING SOME KIND OF PROP PROTECTOR THEN HOOK "CanPlayerUnfreeze"
if ( !gamemode.Call( "CanPlayerUnfreeze", ply, ent, object ) ) then return 0 end
object:EnableMotion( true )
object:Wake()
gamemode.Call( "PlayerUnfrozeObject", ply, ent, object )
return 1
end
--[[---------------------------------------------------------
Name: UnfreezePhysicsObjects
Desc: For the Physgun, unfreezes all frozen physics objects
-----------------------------------------------------------]]
function meta:PhysgunUnfreeze()
-- Get the player's table
local tab = self:GetTable()
if ( !tab.FrozenPhysicsObjects ) then return 0 end
-- Detect double click. Unfreeze all objects on double click.
if ( tab.LastPhysUnfreeze && CurTime() - tab.LastPhysUnfreeze < 0.25 ) then
return self:UnfreezePhysicsObjects()
end
local tr = self:GetEyeTrace()
if ( tr.HitNonWorld && IsValid( tr.Entity ) ) then
local Ents = constraint.GetAllConstrainedEntities( tr.Entity )
local UnfrozenObjects = 0
for k, ent in pairs( Ents ) do
local objects = ent:GetPhysicsObjectCount()
for i = 1, objects do
local physobject = ent:GetPhysicsObjectNum( i - 1 )
UnfrozenObjects = UnfrozenObjects + PlayerUnfreezeObject( self, ent, physobject )
end
end
return UnfrozenObjects
end
tab.LastPhysUnfreeze = CurTime()
return 0
end
--[[---------------------------------------------------------
Name: UnfreezePhysicsObjects
Desc: For the Physgun, unfreezes all frozen physics objects
-----------------------------------------------------------]]
function meta:UnfreezePhysicsObjects()
-- Get the player's table
local tab = self:GetTable()
-- If the table doesn't exist then quit here
if ( !tab.FrozenPhysicsObjects ) then return 0 end
local Count = 0
-- Loop through each table in our table
for k, v in pairs( tab.FrozenPhysicsObjects ) do
-- Make sure the entity to which the physics object
-- is attached is still valid (still exists)
if ( isentity( v.ent ) && IsValid( v.ent ) ) then
-- We can't directly test to see if EnableMotion is false right now
-- but IsMovable seems to do the job just fine.
-- We only test so the count isn't wrong
if ( IsValid( v.phys ) && !v.phys:IsMoveable() ) then
-- We need to freeze/unfreeze all physobj's in jeeps to stop it spazzing
if ( v.ent:GetClass() == "prop_vehicle_jeep" ) then
-- How many physics objects we have
local objects = v.ent:GetPhysicsObjectCount()
-- Loop through each one
for i = 0, objects - 1 do
local physobject = v.ent:GetPhysicsObjectNum( i )
PlayerUnfreezeObject( self, v.ent, physobject )
end
end
Count = Count + PlayerUnfreezeObject( self, v.ent, v.phys )
end
end
end
-- Remove the table
tab.FrozenPhysicsObjects = nil
return Count
end
local g_UniqueIDTable = {}
--[[---------------------------------------------------------
This table will persist between client deaths and reconnects
-----------------------------------------------------------]]
function meta:UniqueIDTable( key )
local id = 0
if ( SERVER ) then id = self:SteamID64() end
g_UniqueIDTable[ id ] = g_UniqueIDTable[ id ] or {}
g_UniqueIDTable[ id ][ key ] = g_UniqueIDTable[ id ][ key ] or {}
return g_UniqueIDTable[ id ][ key ]
end
--[[---------------------------------------------------------
Player Eye Trace
-----------------------------------------------------------]]
function meta:GetEyeTrace()
if ( CLIENT ) then
local framenum = FrameNumber()
-- Cache the trace results for the current frame, unless we're serverside
-- in which case it wouldn't play well with lag compensation at all
if ( self.LastPlayerTrace == framenum ) then
return self.PlayerTrace
end
self.LastPlayerTrace = framenum
end
local tr = util.TraceLine( util.GetPlayerTrace( self ) )
self.PlayerTrace = tr
return tr
end
--[[---------------------------------------------------------
GetEyeTraceIgnoreCursor
Like GetEyeTrace but doesn't use the cursor aim vector..
-----------------------------------------------------------]]
function meta:GetEyeTraceNoCursor()
if ( CLIENT ) then
local framenum = FrameNumber()
if ( self.LastPlayerAimTrace == framenum ) then
return self.PlayerAimTrace
end
self.LastPlayerAimTrace = framenum
end
local tr = util.TraceLine( util.GetPlayerTrace( self, self:EyeAngles():Forward() ) )
self.PlayerAimTrace = tr
return tr
end

View File

@@ -0,0 +1,861 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
--[[---------------------------------------------------------
Name: gamemode:OnPhysgunFreeze( weapon, phys, ent, player )
Desc: The physgun wants to freeze a prop
-----------------------------------------------------------]]
function GM:OnPhysgunFreeze( weapon, phys, ent, ply )
-- Non vphysics entity, we don't know how to handle that
if ( !IsValid( phys ) ) then return end
-- Object is already frozen (!?)
if ( !phys:IsMoveable() ) then return end
if ( ent:GetUnFreezable() ) then return end
phys:EnableMotion( false )
-- Add it to the player's frozen props
ply:AddFrozenPhysicsObject( ent, phys )
end
--[[---------------------------------------------------------
Name: gamemode:OnPhysgunReload( weapon, player )
Desc: The physgun wants to freeze a prop
-----------------------------------------------------------]]
function GM:OnPhysgunReload( weapon, ply )
ply:PhysgunUnfreeze()
end
--[[---------------------------------------------------------
Name: gamemode:PlayerAuthed()
Desc: Player's STEAMID has been authed
-----------------------------------------------------------]]
function GM:PlayerAuthed( ply, SteamID, UniqueID )
end
--[[---------------------------------------------------------
Name: gamemode:PlayerCanPickupWeapon()
Desc: Called when a player tries to pickup a weapon.
return true to allow the pickup.
-----------------------------------------------------------]]
function GM:PlayerCanPickupWeapon( ply, entity )
return true
end
--[[---------------------------------------------------------
Name: gamemode:PlayerCanPickupItem()
Desc: Called when a player tries to pickup an item.
return true to allow the pickup.
-----------------------------------------------------------]]
function GM:PlayerCanPickupItem( ply, entity )
return true
end
--[[---------------------------------------------------------
Name: gamemode:CanPlayerUnfreeze()
Desc: Can the player unfreeze this entity & physobject
-----------------------------------------------------------]]
function GM:CanPlayerUnfreeze( ply, entity, physobject )
return true
end
--[[---------------------------------------------------------
Name: gamemode:PlayerDisconnected()
Desc: Player has disconnected from the server.
-----------------------------------------------------------]]
function GM:PlayerDisconnected( ply )
end
--[[---------------------------------------------------------
Name: gamemode:PlayerSay()
Desc: A player (or server) has used say. Return a string
for the player to say. Return an empty string if the
player should say nothing.
-----------------------------------------------------------]]
function GM:PlayerSay( ply, text, teamonly )
return text
end
--[[---------------------------------------------------------
Name: gamemode:PlayerDeathThink( player )
Desc: Called when the player is waiting to respawn
-----------------------------------------------------------]]
function GM:PlayerDeathThink( pl )
if ( pl.NextSpawnTime && pl.NextSpawnTime > CurTime() ) then return end
if ( pl:IsBot() || pl:KeyPressed( IN_ATTACK ) || pl:KeyPressed( IN_ATTACK2 ) || pl:KeyPressed( IN_JUMP ) ) then
pl:Spawn()
end
end
--[[---------------------------------------------------------
Name: gamemode:PlayerUse( player, entity )
Desc: A player has attempted to use a specific entity
Return true if the player can use it
------------------------------------------------------------]]
function GM:PlayerUse( ply, entity )
return true
end
--[[---------------------------------------------------------
Name: gamemode:PlayerSilentDeath()
Desc: Called when a player dies silently
-----------------------------------------------------------]]
function GM:PlayerSilentDeath( Victim )
Victim.NextSpawnTime = CurTime() + 2
Victim.DeathTime = CurTime()
end
--[[---------------------------------------------------------
Name: gamemode:PlayerDeath()
Desc: Called when a player dies.
-----------------------------------------------------------]]
function GM:PlayerDeath( ply, inflictor, attacker )
-- Don't spawn for at least 2 seconds
ply.NextSpawnTime = CurTime() + 2
ply.DeathTime = CurTime()
if ( IsValid( attacker ) && attacker:GetClass() == "trigger_hurt" ) then attacker = ply end
if ( IsValid( attacker ) && attacker:IsVehicle() && IsValid( attacker:GetDriver() ) ) then
attacker = attacker:GetDriver()
end
if ( !IsValid( inflictor ) && IsValid( attacker ) ) then
inflictor = attacker
end
-- Convert the inflictor to the weapon that they're holding if we can.
-- This can be right or wrong with NPCs since combine can be holding a
-- pistol but kill you by hitting you with their arm.
if ( IsValid( inflictor ) && inflictor == attacker && ( inflictor:IsPlayer() || inflictor:IsNPC() ) ) then
inflictor = inflictor:GetActiveWeapon()
if ( !IsValid( inflictor ) ) then inflictor = attacker end
end
player_manager.RunClass( ply, "Death", inflictor, attacker )
if ( attacker == ply ) then
self:SendDeathNotice( nil, "suicide", ply, 0 )
MsgAll( attacker:Nick() .. " suicided!\n" )
return end
if ( attacker:IsPlayer() ) then
self:SendDeathNotice( attacker, inflictor:GetClass(), ply, 0 )
MsgAll( attacker:Nick() .. " killed " .. ply:Nick() .. " using " .. inflictor:GetClass() .. "\n" )
return end
local flags = 0
if ( attacker:IsNPC() and attacker:Disposition( ply ) != D_HT ) then flags = flags + DEATH_NOTICE_FRIENDLY_ATTACKER end
self:SendDeathNotice( self:GetDeathNoticeEntityName( attacker ), inflictor:GetClass(), ply, 0 )
MsgAll( ply:Nick() .. " was killed by " .. attacker:GetClass() .. "\n" )
end
--[[---------------------------------------------------------
Name: gamemode:PlayerInitialSpawn()
Desc: Called just before the player's first spawn
-----------------------------------------------------------]]
function GM:PlayerInitialSpawn( pl, transiton )
pl:SetTeam( TEAM_UNASSIGNED )
if ( GAMEMODE.TeamBased ) then
pl:ConCommand( "gm_showteam" )
end
end
--[[---------------------------------------------------------
Name: gamemode:PlayerSpawnAsSpectator()
Desc: Player spawns as a spectator
-----------------------------------------------------------]]
function GM:PlayerSpawnAsSpectator( pl )
pl:StripWeapons()
if ( pl:Team() == TEAM_UNASSIGNED ) then
pl:Spectate( OBS_MODE_FIXED )
return
end
pl:SetTeam( TEAM_SPECTATOR )
pl:Spectate( OBS_MODE_ROAMING )
end
--[[---------------------------------------------------------
Name: gamemode:PlayerSpawn()
Desc: Called when a player spawns
-----------------------------------------------------------]]
function GM:PlayerSpawn( pl, transiton )
--
-- If the player doesn't have a team in a TeamBased game
-- then spawn him as a spectator
--
if ( self.TeamBased && ( pl:Team() == TEAM_SPECTATOR || pl:Team() == TEAM_UNASSIGNED ) ) then
self:PlayerSpawnAsSpectator( pl )
return
end
-- Stop observer mode
pl:UnSpectate()
player_manager.OnPlayerSpawn( pl, transiton )
player_manager.RunClass( pl, "Spawn" )
-- If we are in transition, do not touch player's weapons
if ( !transiton ) then
-- Call item loadout function
hook.Call( "PlayerLoadout", GAMEMODE, pl )
end
-- Set player model
hook.Call( "PlayerSetModel", GAMEMODE, pl )
pl:SetupHands()
end
--[[---------------------------------------------------------
Name: gamemode:PlayerSetModel()
Desc: Set the player's model
-----------------------------------------------------------]]
function GM:PlayerSetModel( pl )
player_manager.RunClass( pl, "SetModel" )
end
--[[---------------------------------------------------------
Name: gamemode:PlayerSetHandsModel()
Desc: Sets the player's view model hands model
-----------------------------------------------------------]]
function GM:PlayerSetHandsModel( pl, ent )
local info = player_manager.RunClass( pl, "GetHandsModel" )
if ( !info ) then
local playermodel = player_manager.TranslateToPlayerModelName( pl:GetModel() )
info = player_manager.TranslatePlayerHands( playermodel )
end
if ( info ) then
ent:SetModel( info.model )
ent:SetSkin( info.matchBodySkin and pl:GetSkin() or info.skin )
ent:SetBodyGroups( info.body )
end
end
--[[---------------------------------------------------------
Name: gamemode:PlayerLoadout()
Desc: Give the player the default spawning weapons/ammo
-----------------------------------------------------------]]
function GM:PlayerLoadout( pl )
player_manager.RunClass( pl, "Loadout" )
end
--[[---------------------------------------------------------
Name: gamemode:PlayerSelectTeamSpawn( player )
Desc: Find a spawn point entity for this player's team
-----------------------------------------------------------]]
function GM:PlayerSelectTeamSpawn( TeamID, pl )
local SpawnPoints = team.GetSpawnPoints( TeamID )
if ( !SpawnPoints || table.IsEmpty( SpawnPoints ) ) then return end
local ChosenSpawnPoint = nil
for i = 0, 6 do
ChosenSpawnPoint = table.Random( SpawnPoints )
if ( hook.Call( "IsSpawnpointSuitable", GAMEMODE, pl, ChosenSpawnPoint, i == 6 ) ) then
return ChosenSpawnPoint
end
end
return ChosenSpawnPoint
end
--[[---------------------------------------------------------
Name: gamemode:IsSpawnpointSuitable( player )
Desc: Find out if the spawnpoint is suitable or not
-----------------------------------------------------------]]
local spawnpointmin = Vector( -16, -16, 0 )
local spawnpointmax = Vector( 16, 16, 64 )
function GM:IsSpawnpointSuitable( pl, spawnpointent, bMakeSuitable )
local Pos = spawnpointent:GetPos()
-- Note that we're searching the default hull size here for a player in the way of our spawning.
-- This seems pretty rough, seeing as our player's hull could be different.. but it should do the job
-- (HL2DM kills everything within a 128 unit radius)
if ( pl:Team() == TEAM_SPECTATOR ) then return true end
local Blockers = 0
for k, v in ipairs( ents.FindInBox( Pos + spawnpointmin, Pos + spawnpointmax ) ) do
if ( IsValid( v ) && v != pl && v:GetClass() == "player" && v:Alive() ) then
Blockers = Blockers + 1
if ( bMakeSuitable ) then
v:Kill()
end
end
end
if ( bMakeSuitable ) then return true end
if ( Blockers > 0 ) then return false end
return true
end
--[[---------------------------------------------------------
Name: gamemode:PlayerSelectSpawn( player )
Desc: Find a spawn point entity for this player
-----------------------------------------------------------]]
function GM:PlayerSelectSpawn( pl, transiton )
-- If we are in transition, do not reset player's position
if ( transiton ) then return end
if ( self.TeamBased ) then
local ent = self:PlayerSelectTeamSpawn( pl:Team(), pl )
if ( IsValid( ent ) ) then return ent end
end
-- Save information about all of the spawn points
-- in a team based game you'd split up the spawns
if ( !IsTableOfEntitiesValid( self.SpawnPoints ) ) then
self.LastSpawnPoint = 0
self.SpawnPoints = ents.FindByClass( "info_player_start" )
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_deathmatch" ) )
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_combine" ) )
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_rebel" ) )
-- CS Maps
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_counterterrorist" ) )
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_terrorist" ) )
-- DOD Maps
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_axis" ) )
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_allies" ) )
-- (Old) GMod Maps
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "gmod_player_start" ) )
-- TF Maps
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_teamspawn" ) )
-- INS Maps
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "ins_spawnpoint" ) )
-- AOC Maps
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "aoc_spawnpoint" ) )
-- Dystopia Maps
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "dys_spawn_point" ) )
-- PVKII Maps
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_pirate" ) )
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_viking" ) )
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_knight" ) )
-- DIPRIP Maps
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "diprip_start_team_blue" ) )
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "diprip_start_team_red" ) )
-- OB Maps
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_red" ) )
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_blue" ) )
-- SYN Maps
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_coop" ) )
-- ZPS Maps
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_human" ) )
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_zombie" ) )
-- ZM Maps
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_zombiemaster" ) )
-- FOF Maps
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_fof" ) )
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_desperado" ) )
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_vigilante" ) )
-- L4D Maps
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_survivor_rescue" ) )
-- Removing this one for the time being, c1m4_atrium has one of these in a box under the map
--self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_survivor_position" ) )
end
local Count = table.Count( self.SpawnPoints )
if ( Count == 0 ) then
Msg("[PlayerSelectSpawn] Error! No spawn points!\n")
return nil
end
-- If any of the spawnpoints have a MASTER flag then only use that one.
-- This is needed for single player maps.
for k, v in pairs( self.SpawnPoints ) do
if ( v:HasSpawnFlags( 1 ) && hook.Call( "IsSpawnpointSuitable", GAMEMODE, pl, v, true ) ) then
return v
end
end
local ChosenSpawnPoint = nil
-- Try to work out the best, random spawnpoint
for i = 1, Count do
ChosenSpawnPoint = table.Random( self.SpawnPoints )
if ( IsValid( ChosenSpawnPoint ) && ChosenSpawnPoint:IsInWorld() ) then
if ( ( ChosenSpawnPoint == pl:GetVar( "LastSpawnpoint" ) || ChosenSpawnPoint == self.LastSpawnPoint ) && Count > 1 ) then continue end
if ( hook.Call( "IsSpawnpointSuitable", GAMEMODE, pl, ChosenSpawnPoint, i == Count ) ) then
self.LastSpawnPoint = ChosenSpawnPoint
pl:SetVar( "LastSpawnpoint", ChosenSpawnPoint )
return ChosenSpawnPoint
end
end
end
return ChosenSpawnPoint
end
--[[---------------------------------------------------------
Name: gamemode:WeaponEquip( weapon )
Desc: Player just picked up (or was given) weapon
-----------------------------------------------------------]]
function GM:WeaponEquip( weapon )
end
--[[---------------------------------------------------------
Name: gamemode:ScalePlayerDamage( ply, hitgroup, dmginfo )
Desc: Scale the damage based on being shot in a hitbox
Return true to not take damage
-----------------------------------------------------------]]
function GM:ScalePlayerDamage( ply, hitgroup, dmginfo )
-- More damage if we're shot in the head
if ( hitgroup == HITGROUP_HEAD ) then
dmginfo:ScaleDamage( 2 )
end
-- Less damage if we're shot in the arms or legs
if ( hitgroup == HITGROUP_LEFTARM ||
hitgroup == HITGROUP_RIGHTARM ||
hitgroup == HITGROUP_LEFTLEG ||
hitgroup == HITGROUP_RIGHTLEG ||
hitgroup == HITGROUP_GEAR ) then
dmginfo:ScaleDamage( 0.25 )
end
end
--[[---------------------------------------------------------
Name: gamemode:PlayerDeathSound()
Desc: Return true to not play the default sounds
-----------------------------------------------------------]]
function GM:PlayerDeathSound()
return false
end
--[[---------------------------------------------------------
Name: gamemode:SetupPlayerVisibility()
Desc: Add extra positions to the player's PVS
-----------------------------------------------------------]]
function GM:SetupPlayerVisibility( pPlayer, pViewEntity )
--AddOriginToPVS( vector_position_here )
end
--[[---------------------------------------------------------
Name: gamemode:OnDamagedByExplosion( ply, dmginfo)
Desc: Player has been hurt by an explosion
-----------------------------------------------------------]]
function GM:OnDamagedByExplosion( ply, dmginfo )
ply:SetDSP( 35, false )
end
--[[---------------------------------------------------------
Name: gamemode:CanPlayerSuicide( ply )
Desc: Player typed KILL in the console. Can they kill themselves?
-----------------------------------------------------------]]
function GM:CanPlayerSuicide( ply )
return true
end
--[[---------------------------------------------------------
Name: gamemode:CanPlayerEnterVehicle( player, vehicle, role )
Desc: Return true if player can enter vehicle
-----------------------------------------------------------]]
function GM:CanPlayerEnterVehicle( ply, vehicle, role )
return true
end
--[[---------------------------------------------------------
Name: gamemode:PlayerEnteredVehicle( player, vehicle, role )
Desc: Player entered the vehicle fine
-----------------------------------------------------------]]
function GM:PlayerEnteredVehicle( ply, vehicle, role )
end
--[[---------------------------------------------------------
Name: gamemode:CanExitVehicle()
Desc: If the player is allowed to leave the vehicle, return true
-----------------------------------------------------------]]
function GM:CanExitVehicle( vehicle, passenger )
return true
end
--[[---------------------------------------------------------
Name: gamemode:PlayerLeaveVehicle()
Desc: Player left the vehicle
-----------------------------------------------------------]]
function GM:PlayerLeaveVehicle( ply, vehicle )
end
--[[---------------------------------------------------------
Name: gamemode:PlayerSwitchFlashlight()
Desc: Return true to allow action
-----------------------------------------------------------]]
function GM:PlayerSwitchFlashlight( ply, SwitchOn )
return ply:CanUseFlashlight()
end
--[[---------------------------------------------------------
Name: gamemode:PlayerCanJoinTeam( ply, teamid )
Desc: Allow mods/addons to easily determine whether a player
can join a team or not
-----------------------------------------------------------]]
function GM:PlayerCanJoinTeam( ply, teamid )
local TimeBetweenSwitches = GAMEMODE.SecondsBetweenTeamSwitches or 10
if ( ply.LastTeamSwitch && RealTime() - ply.LastTeamSwitch < TimeBetweenSwitches ) then
ply.LastTeamSwitch = ply.LastTeamSwitch + 1
ply:ChatPrint( Format( "Please wait %i more seconds before trying to change team again", ( TimeBetweenSwitches - ( RealTime() - ply.LastTeamSwitch ) ) + 1 ) )
return false
end
-- Already on this team!
if ( ply:Team() == teamid ) then
ply:ChatPrint( "You're already on that team" )
return false
end
return true
end
--[[---------------------------------------------------------
Name: gamemode:PlayerRequestTeam()
Desc: Player wants to change team
-----------------------------------------------------------]]
function GM:PlayerRequestTeam( ply, teamid )
-- No changing teams if not teambased!
if ( !GAMEMODE.TeamBased ) then return end
-- This team isn't joinable
if ( !team.Joinable( teamid ) ) then
ply:ChatPrint( "You can't join that team" )
return end
-- This team isn't joinable
if ( !GAMEMODE:PlayerCanJoinTeam( ply, teamid ) ) then
-- Messages here should be outputted by this function
return end
GAMEMODE:PlayerJoinTeam( ply, teamid )
end
--[[---------------------------------------------------------
Name: gamemode:PlayerJoinTeam()
Desc: Make player join this team
-----------------------------------------------------------]]
function GM:PlayerJoinTeam( ply, teamid )
local iOldTeam = ply:Team()
if ( ply:Alive() ) then
if ( iOldTeam == TEAM_SPECTATOR || iOldTeam == TEAM_UNASSIGNED ) then
ply:KillSilent()
else
ply:Kill()
end
end
ply:SetTeam( teamid )
ply.LastTeamSwitch = RealTime()
GAMEMODE:OnPlayerChangedTeam( ply, iOldTeam, teamid )
end
--[[---------------------------------------------------------
Name: gamemode:OnPlayerChangedTeam( ply, oldteam, newteam )
-----------------------------------------------------------]]
function GM:OnPlayerChangedTeam( ply, oldteam, newteam )
-- Here's an immediate respawn thing by default. If you want to
-- re-create something more like CS or some shit you could probably
-- change to a spectator or something while dead.
if ( newteam == TEAM_SPECTATOR ) then
-- If we changed to spectator mode, respawn where we are
local Pos = ply:EyePos()
ply:Spawn()
ply:SetPos( Pos )
elseif ( oldteam == TEAM_SPECTATOR ) then
-- If we're changing from spectator, join the game
ply:Spawn()
else
-- If we're straight up changing teams just hang
-- around until we're ready to respawn onto the
-- team that we chose
end
PrintMessage( HUD_PRINTTALK, Format( "%s joined '%s'", ply:Nick(), team.GetName( newteam ) ) )
end
--[[---------------------------------------------------------
Name: gamemode:PlayerSpray()
Desc: Return true to prevent player spraying
-----------------------------------------------------------]]
function GM:PlayerSpray( ply )
return false
end
--[[---------------------------------------------------------
Name: gamemode:OnPlayerHitGround()
Desc: Return true to disable default action
-----------------------------------------------------------]]
function GM:OnPlayerHitGround( ply, bInWater, bOnFloater, flFallSpeed )
-- Apply damage and play collision sound here
-- then return true to disable the default action
--MsgN( ply, bInWater, bOnFloater, flFallSpeed )
--return true
end
--[[---------------------------------------------------------
Name: gamemode:GetFallDamage()
Desc: return amount of damage to do due to fall
-----------------------------------------------------------]]
local mp_falldamage = GetConVar( "mp_falldamage" )
function GM:GetFallDamage( ply, flFallSpeed )
if ( mp_falldamage:GetBool() ) then -- realistic fall damage is on
return ( flFallSpeed - 526.5 ) * ( 100 / 396 ) -- the Source SDK value
end
return 10
end
--[[---------------------------------------------------------
Name: gamemode:PlayerCanSeePlayersChat()
Desc: Can this player see the other player's chat?
-----------------------------------------------------------]]
function GM:PlayerCanSeePlayersChat( strText, bTeamOnly, pListener, pSpeaker )
if ( bTeamOnly ) then
if ( !IsValid( pSpeaker ) || !IsValid( pListener ) ) then return false end
if ( pListener:Team() != pSpeaker:Team() ) then return false end
end
return true
end
local sv_alltalk = GetConVar( "sv_alltalk" )
--[[---------------------------------------------------------
Name: gamemode:PlayerCanHearPlayersVoice()
Desc: Can this player see the other player's voice?
Returns 2 bools.
1. Can the player hear the other player
2. Can they hear them spacially
-----------------------------------------------------------]]
function GM:PlayerCanHearPlayersVoice( pListener, pTalker )
local alltalk = sv_alltalk:GetInt()
if ( alltalk >= 1 ) then return true, alltalk == 2 end
return pListener:Team() == pTalker:Team(), false
end
--[[---------------------------------------------------------
Name: gamemode:NetworkIDValidated()
Desc: Called when Steam has validated this as a valid player
-----------------------------------------------------------]]
function GM:NetworkIDValidated( name, steamid )
-- MsgN( "GM:NetworkIDValidated", name, steamid )
end
--[[---------------------------------------------------------
Name: gamemode:PlayerShouldTaunt( ply, actid )
-----------------------------------------------------------]]
function GM:PlayerShouldTaunt( ply, actid )
-- The default behaviour is to always let them act
-- Some gamemodes will obviously want to stop this for certain players by returning false
return true
end
--[[---------------------------------------------------------
Name: gamemode:PlayerStartTaunt( ply, actid, length )
-----------------------------------------------------------]]
function GM:PlayerStartTaunt( ply, actid, length )
end
--[[---------------------------------------------------------
Name: gamemode:AllowPlayerPickup( ply, object )
-----------------------------------------------------------]]
function GM:AllowPlayerPickup( ply, object )
-- Should the player be allowed to pick this object up (using ENTER)?
-- If no then return false. Default is HELL YEAH
return true
end
--[[---------------------------------------------------------
Name: gamemode:PlayerDroppedWeapon()
Desc: Player has dropped a weapon
-----------------------------------------------------------]]
function GM:PlayerDroppedWeapon( ply, weapon )
end
--[[---------------------------------------------------------
These are buttons that the client is pressing. They're used
in Sandbox mode to control things like wheels, thrusters etc.
-----------------------------------------------------------]]
function GM:PlayerButtonDown( ply, btn ) end
function GM:PlayerButtonUp( ply, btn ) end
concommand.Add( "changeteam", function( pl, cmd, args ) hook.Call( "PlayerRequestTeam", GAMEMODE, pl, tonumber( args[ 1 ] ) ) end )
--[[---------------------------------------------------------
Name: gamemode:HandlePlayerArmorReduction()
Desc: Handle player armor reduction
-----------------------------------------------------------]]
function GM:HandlePlayerArmorReduction( ply, dmginfo )
-- If no armor, or special damage types, bypass armor
if ( ply:Armor() <= 0 || bit.band( dmginfo:GetDamageType(), DMG_FALL + DMG_DROWN + DMG_POISON + DMG_RADIATION ) != 0 ) then return end
local flBonus = 1.0 -- Each Point of Armor is worth 1/x points of health
local flRatio = 0.2 -- Armor Takes 80% of the damage
if ( GetConVar( "player_old_armor" ):GetBool() ) then
flBonus = 0.5
end
local flNew = dmginfo:GetDamage() * flRatio
local flArmor = (dmginfo:GetDamage() - flNew) * flBonus
if ( !GetConVar( "player_old_armor" ):GetBool() ) then
if ( flArmor < 0.1 ) then flArmor = 0 end -- Let's not have tiny amounts of damage reduce a lot of our armor
else if ( flArmor < 1.0 ) then flArmor = 1.0 end
end
-- Does this use more armor than we have?
if ( flArmor > ply:Armor() ) then
flArmor = ply:Armor() * ( 1 / flBonus )
flNew = dmginfo:GetDamage() - flArmor
ply:SetArmor( 0 )
else
ply:SetArmor( ply:Armor() - flArmor )
end
dmginfo:SetDamage( flNew )
end

View File

@@ -0,0 +1,145 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
AddCSLuaFile()
include( "taunt_camera.lua" )
local PLAYER = {}
PLAYER.DisplayName = "Default Class"
PLAYER.SlowWalkSpeed = 200 -- How fast to move when slow-walking (+WALK)
PLAYER.WalkSpeed = 400 -- How fast to move when not running
PLAYER.RunSpeed = 600 -- How fast to move when running
PLAYER.CrouchedWalkSpeed = 0.3 -- Multiply move speed by this when crouching
PLAYER.DuckSpeed = 0.3 -- How fast to go from not ducking, to ducking
PLAYER.UnDuckSpeed = 0.3 -- How fast to go from ducking, to not ducking
PLAYER.JumpPower = 200 -- How powerful our jump should be
PLAYER.CanUseFlashlight = true -- Can we use the flashlight
PLAYER.MaxHealth = 100 -- Max health we can have
PLAYER.MaxArmor = 100 -- Max armor we can have
PLAYER.StartHealth = 100 -- How much health we start with
PLAYER.StartArmor = 0 -- How much armour we start with
PLAYER.DropWeaponOnDie = false -- Do we drop our weapon when we die
PLAYER.TeammateNoCollide = true -- Do we collide with teammates or run straight through them
PLAYER.AvoidPlayers = true -- Automatically swerves around other players
PLAYER.UseVMHands = true -- Uses viewmodel hands
--
-- Name: PLAYER:SetupDataTables
-- Desc: Set up the network table accessors
-- Arg1:
-- Ret1:
--
function PLAYER:SetupDataTables()
end
--
-- Name: PLAYER:Init
-- Desc: Called when the class object is created (shared)
-- Arg1:
-- Ret1:
--
function PLAYER:Init()
end
--
-- Name: PLAYER:Spawn
-- Desc: Called serverside only when the player spawns
-- Arg1:
-- Ret1:
--
function PLAYER:Spawn()
end
--
-- Name: PLAYER:Loadout
-- Desc: Called on spawn to give the player their default loadout
-- Arg1:
-- Ret1:
--
function PLAYER:Loadout()
self.Player:Give( "weapon_pistol" )
self.Player:GiveAmmo( 255, "Pistol", true )
end
function PLAYER:SetModel()
local cl_playermodel = self.Player:GetInfo( "cl_playermodel" )
local modelname = player_manager.TranslatePlayerModel( cl_playermodel )
util.PrecacheModel( modelname )
self.Player:SetModel( modelname )
end
function PLAYER:Death( inflictor, attacker )
end
-- Clientside only
function PLAYER:CalcView( view ) end -- Setup the player's view
function PLAYER:CreateMove( cmd ) end -- Creates the user command on the client
function PLAYER:ShouldDrawLocal() end -- Return true if we should draw the local player
-- Shared
function PLAYER:StartMove( cmd, mv ) end -- Copies from the user command to the move
function PLAYER:Move( mv ) end -- Runs the move (can run multiple times for the same client)
function PLAYER:FinishMove( mv ) end -- Copy the results of the move back to the Player
--
-- Name: PLAYER:ViewModelChanged
-- Desc: Called when the player changes their weapon to another one causing their viewmodel model to change
-- Arg1: Entity|viewmodel|The viewmodel that is changing
-- Arg2: string|old|The old model
-- Arg3: string|new|The new model
-- Ret1:
--
function PLAYER:ViewModelChanged( vm, old, new )
end
--
-- Name: PLAYER:PreDrawViewmodel
-- Desc: Called before the viewmodel is being drawn (clientside)
-- Arg1: Entity|viewmodel|The viewmodel
-- Arg2: Entity|weapon|The weapon
-- Ret1:
--
function PLAYER:PreDrawViewModel( vm, weapon )
end
--
-- Name: PLAYER:PostDrawViewModel
-- Desc: Called after the viewmodel has been drawn (clientside)
-- Arg1: Entity|viewmodel|The viewmodel
-- Arg2: Entity|weapon|The weapon
-- Ret1:
--
function PLAYER:PostDrawViewModel( vm, weapon )
end
--
-- Name: PLAYER:GetHandsModel
-- Desc: Called on player spawn to determine which hand model to use
-- Arg1:
-- Ret1: table|info|A table containing model, skin and body
--
function PLAYER:GetHandsModel()
-- return { model = "models/weapons/c_arms_cstrike.mdl", skin = 1, body = "0100000" }
local playermodel = player_manager.TranslateToPlayerModelName( self.Player:GetModel() )
return player_manager.TranslatePlayerHands( playermodel )
end
player_manager.RegisterClass( "player_default", PLAYER, nil )

View File

@@ -0,0 +1,133 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
AddCSLuaFile()
--
-- This is designed so you can call it like
--
-- tauntcam = TauntCamera()
--
-- Then you have your own copy.
--
function TauntCamera()
local CAM = {}
local WasOn = false
local CustomAngles = angle_zero
local PlayerLockAngles = nil
local InLerp = 0
local OutLerp = 1
--
-- Draw the local player if we're active in any way
--
CAM.ShouldDrawLocalPlayer = function( self, ply, on )
return on || OutLerp < 1
end
--
-- Implements the third person, rotation view (with lerping in/out)
--
CAM.CalcView = function( self, view, ply, on )
if ( !ply:Alive() || !IsValid( ply:GetViewEntity() ) || ply:GetViewEntity() != ply ) then on = false end
if ( WasOn != on ) then
if ( on ) then InLerp = 0 end
if ( !on ) then OutLerp = 0 end
WasOn = on
end
if ( !on && OutLerp >= 1 ) then
CustomAngles = view.angles * 1
CustomAngles.r = 0
PlayerLockAngles = nil
InLerp = 0
return
end
if ( PlayerLockAngles == nil ) then return end
--
-- Simple 3rd person camera
--
local TargetOrigin = view.origin - CustomAngles:Forward() * 100
local tr = util.TraceHull( { start = view.origin, endpos = TargetOrigin, mask = MASK_SHOT, filter = player.GetAll(), mins = Vector( -8, -8, -8 ), maxs = Vector( 8, 8, 8 ) } )
TargetOrigin = tr.HitPos + tr.HitNormal
if ( InLerp < 1 ) then
InLerp = InLerp + FrameTime() * 5.0
view.origin = LerpVector( InLerp, view.origin, TargetOrigin )
view.angles = LerpAngle( InLerp, PlayerLockAngles, CustomAngles )
return true
end
if ( OutLerp < 1 ) then
OutLerp = OutLerp + FrameTime() * 3.0
view.origin = LerpVector( 1-OutLerp, view.origin, TargetOrigin )
view.angles = LerpAngle( 1-OutLerp, PlayerLockAngles, CustomAngles )
return true
end
view.angles = CustomAngles * 1
view.origin = TargetOrigin
return true
end
--
-- Freezes the player in position and uses the input from the user command to
-- rotate the custom third person camera
--
CAM.CreateMove = function( self, cmd, ply, on )
if ( !ply:Alive() ) then on = false end
if ( !on ) then return end
if ( PlayerLockAngles == nil ) then
PlayerLockAngles = CustomAngles * 1
end
--
-- Rotate our view
--
CustomAngles.pitch = CustomAngles.pitch + cmd:GetMouseY() * 0.01
CustomAngles.yaw = CustomAngles.yaw - cmd:GetMouseX() * 0.01
--
-- Lock the player's controls and angles
--
cmd:SetViewAngles( PlayerLockAngles )
cmd:ClearButtons()
cmd:ClearMovement()
return true
end
return CAM
end

View File

@@ -0,0 +1,145 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
--[[---------------------------------------------------------
Name: gamemode:PlayerTraceAttack( )
Desc: A bullet has been fired and hit this player
Return true to completely override internals
-----------------------------------------------------------]]
function GM:PlayerTraceAttack( ply, dmginfo, dir, trace )
return false
end
--[[---------------------------------------------------------
Name: gamemode:SetPlayerSpeed( )
Desc: Sets the player's run/walk speed
-----------------------------------------------------------]]
function GM:SetPlayerSpeed( ply, walk, run )
ply:SetWalkSpeed( walk )
ply:SetRunSpeed( run )
end
--[[---------------------------------------------------------
Name: gamemode:PlayerFootstep( ply, vPos, iFoot, strSoundName, fVolume, pFilter )
Desc: Called when a player steps
pFilter is the recipient filter to use for effects/sounds
and is only valid SERVERSIDE. Clientside needs no filter!
Return true to not play normal sound
-----------------------------------------------------------]]
function GM:PlayerFootstep( ply, vPos, iFoot, strSoundName, fVolume, pFilter )
if ( IsValid( ply ) and !ply:Alive() ) then
return true
end
--[[
-- Draw effect on footdown
local effectdata = EffectData()
effectdata:SetOrigin( vPos )
util.Effect( "phys_unfreeze", effectdata, true, pFilter )
--]]
--[[
-- Don't play left foot
if ( iFoot == 0 ) then return true end
--]]
end
--[[---------------------------------------------------------
Name: gamemode:PlayerStepSoundTime( ply, iType, bWalking )
Desc: Return the time between footsteps
-----------------------------------------------------------]]
function GM:PlayerStepSoundTime( ply, iType, bWalking )
local fStepTime = 350
local fMaxSpeed = ply:GetMaxSpeed()
if ( iType == STEPSOUNDTIME_NORMAL || iType == STEPSOUNDTIME_WATER_FOOT ) then
if ( fMaxSpeed <= 100 ) then
fStepTime = 400
elseif ( fMaxSpeed <= 300 ) then
fStepTime = 350
else
fStepTime = 250
end
elseif ( iType == STEPSOUNDTIME_ON_LADDER ) then
fStepTime = 450
elseif ( iType == STEPSOUNDTIME_WATER_KNEE ) then
fStepTime = 600
end
-- Step slower if crouching
if ( ply:Crouching() ) then
fStepTime = fStepTime + 50
end
return fStepTime
end
--[[---------------------------------------------------------
Name: gamemode:PlayerNoClip( player, bool )
Desc: Player pressed the noclip key, return true if
the player is allowed to noclip, false to block
-----------------------------------------------------------]]
function GM:PlayerNoClip( pl, on )
if ( !on ) then return true end
-- Allow noclip if we're in single player and living
return game.SinglePlayer() && IsValid( pl ) && pl:Alive()
end
--
-- FindUseEntity
--
function GM:FindUseEntity( ply, ent )
-- ent is what the game found to use by default
-- return what you REALLY want it to use
-- Simple fix to allow entities inside playerclip brushes to be used. Necessary for c1a0c map in Half-Life: Source
if ( !IsValid( ent ) ) then
local traceEnt = util.TraceLine( {
start = ply:GetShootPos(),
endpos = ply:GetShootPos() + ply:GetAimVector() * 72,
filter = ply
} ).Entity
if ( IsValid( traceEnt ) ) then return traceEnt end
end
return ent
end
--
-- Player tick
--
function GM:PlayerTick( ply, mv )
end
--
-- Player is switching weapon. Return true to prevent the switch.
--
function GM:PlayerSwitchWeapon( ply, oldwep, newwep )
return false
end

View File

@@ -0,0 +1,282 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
--[[---------------------------------------------------------
This file should contain variables and functions that are
the same on both client and server.
This file will get sent to the client - so don't add
anything to this file that you don't want them to be
able to see.
-----------------------------------------------------------]]
include( "obj_player_extend.lua" )
include( "gravitygun.lua" )
include( "player_shd.lua" )
include( "animations.lua" )
include( "player_class/player_default.lua" )
GM.Name = "Base Gamemode"
GM.Author = "Garry Newman"
GM.Email = "garrynewman@gmail.com"
GM.Website = "www.garry.tv"
GM.TeamBased = false
--[[---------------------------------------------------------
Name: gamemode:KeyPress( )
Desc: Player pressed a key (see IN enums)
-----------------------------------------------------------]]
function GM:KeyPress( player, key )
end
--[[---------------------------------------------------------
Name: gamemode:KeyRelease( )
Desc: Player released a key (see IN enums)
-----------------------------------------------------------]]
function GM:KeyRelease( player, key )
end
--[[---------------------------------------------------------
Name: gamemode:PlayerConnect( )
Desc: Player has connects to the server (hasn't spawned)
-----------------------------------------------------------]]
function GM:PlayerConnect( name, address )
end
--[[---------------------------------------------------------
Name: gamemode:PropBreak( )
Desc: Prop has been broken
-----------------------------------------------------------]]
function GM:PropBreak( attacker, prop )
end
--[[---------------------------------------------------------
Name: gamemode:PhysgunPickup( )
Desc: Return true if player can pickup entity
-----------------------------------------------------------]]
function GM:PhysgunPickup( ply, ent )
-- Don't pick up players
if ( ent:GetClass() == "player" ) then return false end
return true
end
--[[---------------------------------------------------------
Name: gamemode:PhysgunDrop( )
Desc: Dropped an entity
-----------------------------------------------------------]]
function GM:PhysgunDrop( ply, ent )
end
--[[---------------------------------------------------------
Name: Text to show in the server browser
-----------------------------------------------------------]]
function GM:GetGameDescription()
return self.Name
end
--[[---------------------------------------------------------
Name: Saved
-----------------------------------------------------------]]
function GM:Saved()
end
--[[---------------------------------------------------------
Name: Restored
-----------------------------------------------------------]]
function GM:Restored()
end
--[[---------------------------------------------------------
Name: EntityRemoved
Desc: Called right before an entity is removed. Note that this
isn't going to be totally reliable on the client since the client
only knows about entities that it has had in its PVS.
-----------------------------------------------------------]]
function GM:EntityRemoved( ent )
end
--[[---------------------------------------------------------
Name: Tick
Desc: Like Think except called every tick on both client and server
-----------------------------------------------------------]]
function GM:Tick()
end
--[[---------------------------------------------------------
Name: OnEntityCreated
Desc: Called right after the Entity has been made visible to Lua
-----------------------------------------------------------]]
function GM:OnEntityCreated( Ent )
end
--[[---------------------------------------------------------
Name: gamemode:EntityKeyValue( ent, key, value )
Desc: Called when an entity has a keyvalue set
Returning a string it will override the value
-----------------------------------------------------------]]
function GM:EntityKeyValue( ent, key, value )
end
--[[---------------------------------------------------------
Name: gamemode:CreateTeams()
Desc: Note - HAS to be shared.
-----------------------------------------------------------]]
function GM:CreateTeams()
-- Don't do this if not teambased. But if it is teambased we
-- create a few teams here as an example. If you're making a teambased
-- gamemode you should override this function in your gamemode
if ( !GAMEMODE.TeamBased ) then return end
TEAM_BLUE = 1
team.SetUp( TEAM_BLUE, "Blue Team", Color( 0, 0, 255 ) )
team.SetSpawnPoint( TEAM_BLUE, "ai_hint" ) -- <-- This would be info_terrorist or some entity that is in your map
TEAM_ORANGE = 2
team.SetUp( TEAM_ORANGE, "Orange Team", Color( 255, 150, 0 ) )
team.SetSpawnPoint( TEAM_ORANGE, "sky_camera" ) -- <-- This would be info_terrorist or some entity that is in your map
TEAM_SEXY = 3
team.SetUp( TEAM_SEXY, "Sexy Team", Color( 255, 150, 150 ) )
team.SetSpawnPoint( TEAM_SEXY, "info_player_start" ) -- <-- This would be info_terrorist or some entity that is in your map
team.SetSpawnPoint( TEAM_SPECTATOR, "worldspawn" )
end
--[[---------------------------------------------------------
Name: gamemode:ShouldCollide( Ent1, Ent2 )
Desc: This should always return true unless you have
a good reason for it not to.
-----------------------------------------------------------]]
function GM:ShouldCollide( Ent1, Ent2 )
return true
end
--[[---------------------------------------------------------
Name: gamemode:Move
This basically overrides the NOCLIP, PLAYERMOVE movement stuff.
It's what actually performs the move.
Return true to not perform any default movement actions. (completely override)
-----------------------------------------------------------]]
function GM:Move( ply, mv )
if ( drive.Move( ply, mv ) ) then return true end
if ( player_manager.RunClass( ply, "Move", mv ) ) then return true end
end
--[[---------------------------------------------------------
-- Purpose: This is called pre player movement and copies all the data necessary
-- from the player for movement. Copy from the usercmd to move.
-----------------------------------------------------------]]
function GM:SetupMove( ply, mv, cmd )
if ( drive.StartMove( ply, mv, cmd ) ) then return true end
if ( player_manager.RunClass( ply, "StartMove", mv, cmd ) ) then return true end
end
--[[---------------------------------------------------------
Name: gamemode:FinishMove( player, movedata )
-----------------------------------------------------------]]
function GM:FinishMove( ply, mv )
if ( drive.FinishMove( ply, mv ) ) then return true end
if ( player_manager.RunClass( ply, "FinishMove", mv ) ) then return true end
end
--[[---------------------------------------------------------
Called after the player's think.
-----------------------------------------------------------]]
function GM:PlayerPostThink( ply )
end
--[[---------------------------------------------------------
A player has started driving an entity
-----------------------------------------------------------]]
function GM:StartEntityDriving( ent, ply )
drive.Start( ply, ent )
end
--[[---------------------------------------------------------
A player has stopped driving an entity
-----------------------------------------------------------]]
function GM:EndEntityDriving( ent, ply )
drive.End( ply, ent )
end
--[[---------------------------------------------------------
To update the player's animation during a drive
-----------------------------------------------------------]]
function GM:PlayerDriveAnimate( ply )
end
--[[---------------------------------------------------------
The gamemode has been reloaded
-----------------------------------------------------------]]
function GM:OnReloaded()
end
function GM:PreGamemodeLoaded()
end
function GM:OnGamemodeLoaded()
end
function GM:PostGamemodeLoaded()
end
--
-- Name: GM:OnViewModelChanged
-- Desc: Called when the player changes their weapon to another one - and their viewmodel model changes
-- Arg1: Entity|viewmodel|The viewmodel that is changing
-- Arg2: string|old|The old model
-- Arg3: string|new|The new model
-- Ret1:
--
function GM:OnViewModelChanged( vm, old, new )
local ply = vm:GetOwner()
if ( IsValid( ply ) ) then
player_manager.RunClass( ply, "ViewModelChanged", vm, old, new )
end
end
--[[---------------------------------------------------------
Disable properties serverside for all non-sandbox derived gamemodes.
-----------------------------------------------------------]]
function GM:CanProperty( pl, property, ent )
return false
end
--[[---------------------------------------------------------
Allow hooks to override bullet without ignoring all other hooks
-----------------------------------------------------------]]
function GM:EntityFireBullets( ent, bullets )
return true
end

View File

@@ -0,0 +1,42 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
--
-- Called when we've received a call from a client who wants to edit
-- a particular entity.
--
function GM:VariableEdited( ent, ply, key, val, editor )
if ( !IsValid( ent ) ) then return end
if ( !IsValid( ply ) ) then return end
--
-- Check with the gamemode that we can edit the entity
--
local CanEdit = hook.Run( "CanEditVariable", ent, ply, key, val, editor )
if ( !CanEdit ) then return end
--
-- Actually apply the edited value
--
ent:EditValue( key, val )
end
--
-- Your gamemode should use this hook to allow/dissallow editing
-- By default only admins can edit entities.
--
function GM:CanEditVariable( ent, ply, key, val, editor )
return ply:IsAdmin() || game.SinglePlayer()
end