Initial commit

This commit is contained in:
2026-03-15 14:54:49 +03:00
commit 64f8029c06
4027 changed files with 254888 additions and 0 deletions

View File

@@ -0,0 +1,139 @@
AddCSLuaFile()
if CLIENT then
SWEP.Slot = 1
SWEP.SlotPos = 3
end
DEFINE_BASECLASS("stick_base")
SWEP.Instructions = "Left click to arrest\nRight click to switch batons"
SWEP.IsDarkRPArrestStick = true
SWEP.PrintName = "Arrest Baton"
SWEP.Spawnable = true
SWEP.Category = "DarkRP (Utility)"
SWEP.StickColor = Color(255, 0, 0)
SWEP.Switched = true
DarkRP.hookStub{
name = "canArrest",
description = "Whether someone can arrest another player.",
parameters = {
{
name = "arrester",
description = "The player trying to arrest someone.",
type = "Player"
},
{
name = "arrestee",
description = "The player being arrested.",
type = "Player"
}
},
returns = {
{
name = "canArrest",
description = "A yes or no as to whether the arrester can arrest the arestee.",
type = "boolean"
},
{
name = "message",
description = "The message that is shown when they can't arrest the player.",
type = "string"
}
},
realm = "Server"
}
DarkRP.hookStub{
name = "setArrestStickTime",
description = "Sets arrest time for an arrest made via the arrest stick",
parameters = {
{
name = "arrest_stick",
description = "The arrest strick weapon with which the arrestee was arrested.",
type = "Weapon"
},
{
name = "arrester",
description = "The player trying to arrest someone.",
type = "Player"
},
{
name = "arrestee",
description = "The player being arrested.",
type = "Player"
}
},
returns = {
{
name = "time",
description = "The time to arrest the player.",
type = "integer"
}
},
realm = "Server"
}
function SWEP:Deploy()
self.Switched = true
return BaseClass.Deploy(self)
end
function SWEP:PrimaryAttack()
BaseClass.PrimaryAttack(self)
if CLIENT then return end
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
Owner:LagCompensation(true)
local trace = util.QuickTrace(Owner:EyePos(), Owner:GetAimVector() * 90, {Owner})
Owner:LagCompensation(false)
local ent = trace.Entity
if IsValid(ent) and ent.onArrestStickUsed then
ent:onArrestStickUsed(Owner)
return
end
ent = Owner:getEyeSightHitEntity(nil, nil, function(p) return p ~= Owner and p:IsPlayer() and p:Alive() and p:IsSolid() end)
local stickRange = self.stickRange * self.stickRange
if not IsValid(ent) or (Owner:EyePos():DistToSqr(ent:GetPos()) > stickRange) or not ent:IsPlayer() then
return
end
local canArrest, message = hook.Call("canArrest", DarkRP.hooks, Owner, ent)
if not canArrest then
if message then DarkRP.notify(Owner, 1, 5, message) end
return
end
local time = hook.Call("setArrestStickTime", DarkRP.hooks, self, Owner, ent)
ent:arrest(time, Owner)
DarkRP.notify(ent, 0, 20, DarkRP.getPhrase("youre_arrested_by", Owner:Nick()))
if Owner.SteamName then
DarkRP.log(Owner:Nick() .. " (" .. Owner:SteamID() .. ") arrested " .. ent:Nick(), Color(0, 255, 255))
end
end
function SWEP:startDarkRPCommand(usrcmd)
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
if game.SinglePlayer() and CLIENT then return end
if usrcmd:KeyDown(IN_ATTACK2) then
if not self.Switched and Owner:HasWeapon("unarrest_stick") then
usrcmd:SelectWeapon(Owner:GetWeapon("unarrest_stick"))
end
else
self.Switched = false
end
end

View File

@@ -0,0 +1,319 @@
AddCSLuaFile()
if CLIENT then
SWEP.Slot = 5
SWEP.SlotPos = 1
SWEP.DrawAmmo = false
SWEP.DrawCrosshair = false
end
-- Variables that are used on both client and server
DEFINE_BASECLASS("weapon_cs_base2")
SWEP.PrintName = "Battering Ram"
SWEP.Author = "DarkRP Developers"
SWEP.Instructions = "Left click to break open doors/unfreeze props or get people out of their vehicles\nRight click to raise"
SWEP.Contact = ""
SWEP.Purpose = ""
SWEP.IsDarkRPDoorRam = true
SWEP.IconLetter = ""
SWEP.ViewModelFOV = 62
SWEP.ViewModelFlip = false
SWEP.ViewModel = Model("models/weapons/c_rpg.mdl")
SWEP.WorldModel = Model("models/weapons/w_rocket_launcher.mdl")
SWEP.AnimPrefix = "rpg"
SWEP.UseHands = true
SWEP.Spawnable = true
SWEP.AdminOnly = true
SWEP.Category = "DarkRP (Utility)"
SWEP.Sound = Sound("physics/wood/wood_box_impact_hard3.wav")
SWEP.Primary.ClipSize = -1 -- Size of a clip
SWEP.Primary.DefaultClip = 0 -- Default number of bullets in a clip
SWEP.Primary.Automatic = false -- Automatic/Semi Auto
SWEP.Primary.Ammo = ""
SWEP.Secondary.ClipSize = -1 -- Size of a clip
SWEP.Secondary.DefaultClip = 0 -- Default number of bullets in a clip
SWEP.Secondary.Automatic = false -- Automatic/Semi Auto
SWEP.Secondary.Ammo = ""
--[[---------------------------------------------------------
Name: SWEP:Initialize()
Desc: Called when the weapon is first loaded
---------------------------------------------------------]]
function SWEP:Initialize()
if CLIENT then self.LastIron = CurTime() end
self:SetHoldType("normal")
end
function SWEP:Holster()
self:SetIronsights(false)
return true
end
-- Check whether an object of this player can be rammed
local function canRam(ply)
return IsValid(ply) and (ply.warranted == true or ply:isWanted() or ply:isArrested())
end
-- Ram action when ramming a door
local function ramDoor(ply, trace, ent)
if ply:EyePos():DistToSqr(trace.HitPos) > 2025 or (not GAMEMODE.Config.canforcedooropen and ent:getKeysNonOwnable()) then return false end
local allowed = false
-- if we need a warrant to get in
if GAMEMODE.Config.doorwarrants and ent:isKeysOwned() and not ent:isKeysOwnedBy(ply) then
-- if anyone who owns this door has a warrant for their arrest
-- allow the police to smash the door in
for _, v in ipairs(player.GetAll()) do
if ent:isKeysOwnedBy(v) and canRam(v) then
allowed = true
break
end
end
else
-- door warrants not needed, allow warrantless entry
allowed = true
end
-- Be able to open the door if any member of the door group is warranted
local keysDoorGroup = ent:getKeysDoorGroup()
if GAMEMODE.Config.doorwarrants and keysDoorGroup then
local teamDoors = RPExtraTeamDoors[keysDoorGroup]
if teamDoors then
allowed = false
for _, v in ipairs(player.GetAll()) do
if table.HasValue(teamDoors, v:Team()) and canRam(v) then
allowed = true
break
end
end
end
end
if CLIENT then return allowed end
-- Do we have a warrant for this player?
if not allowed then
DarkRP.notify(ply, 1, 5, DarkRP.getPhrase("warrant_required"))
return false
end
ent:keysUnLock()
ent:Fire("open", "", .6)
ent:Fire("setanimation", "open", .6)
return true
end
-- Ram action when ramming a vehicle
local function ramVehicle(ply, trace, ent)
if ply:EyePos():DistToSqr(trace.HitPos) > 10000 then return false end
if CLIENT then return false end -- Ideally this would return true after ent:GetDriver() check
local driver = ent:GetDriver()
if not IsValid(driver) or not driver.ExitVehicle then return false end
driver:ExitVehicle()
ent:keysLock()
return true
end
-- Ram action when ramming a fading door
local function ramFadingDoor(ply, trace, ent)
if ply:EyePos():DistToSqr(trace.HitPos) > 10000 then return false end
local Owner = ent:CPPIGetOwner()
if CLIENT then return canRam(Owner) end
if not canRam(Owner) then
DarkRP.notify(ply, 1, 5, DarkRP.getPhrase("warrant_required"))
return false
end
if not ent.fadeActive then
ent:fadeActivate()
timer.Simple(5, function() if IsValid(ent) and ent.fadeActive then ent:fadeDeactivate() end end)
end
return true
end
-- Ram action when ramming a frozen prop
local function ramProp(ply, trace, ent)
if ply:EyePos():DistToSqr(trace.HitPos) > 10000 then return false end
if ent:GetClass() ~= "prop_physics" then return false end
local Owner = ent:CPPIGetOwner()
if CLIENT then return canRam(Owner) end
if not canRam(Owner) then
DarkRP.notify(ply, 1, 5, DarkRP.getPhrase(GAMEMODE.Config.copscanunweld and "warrant_required_unweld" or "warrant_required_unfreeze"))
return false
end
if GAMEMODE.Config.copscanunweld then
constraint.RemoveConstraints(ent, "Weld")
end
if GAMEMODE.Config.copscanunfreeze then
ent:GetPhysicsObject():EnableMotion(true)
end
return true
end
-- Decides the behaviour of the ram function for the given entity
local function getRamFunction(ply, trace)
local ent = trace.Entity
if not IsValid(ent) then return fp{fn.Id, false} end
local override = hook.Call("canDoorRam", nil, ply, trace, ent)
return
override ~= nil and fp{fn.Id, override} or
ent:isDoor() and fp{ramDoor, ply, trace, ent} or
ent:IsVehicle() and fp{ramVehicle, ply, trace, ent} or
ent.fadeActivate and fp{ramFadingDoor, ply, trace, ent} or
ent:GetPhysicsObject():IsValid() and not ent:GetPhysicsObject():IsMoveable()
and fp{ramProp, ply, trace, ent} or
fp{fn.Id, false} -- no ramming was performed
end
--[[---------------------------------------------------------
Name: SWEP:PrimaryAttack()
Desc: +attack1 has been pressed
---------------------------------------------------------]]
function SWEP:PrimaryAttack()
if not self:GetIronsights() then return end
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
self:SetNextPrimaryFire(CurTime() + 0.1)
Owner:LagCompensation(true)
local trace = Owner:GetEyeTrace()
Owner:LagCompensation(false)
local hasRammed = getRamFunction(Owner, trace)()
if SERVER then
hook.Call("onDoorRamUsed", GAMEMODE, hasRammed, Owner, trace)
end
if not hasRammed then return end
self:SetNextPrimaryFire(CurTime() + 2.5)
self:SetTotalUsedMagCount(self:GetTotalUsedMagCount() + 1)
Owner:SetAnimation(PLAYER_ATTACK1)
Owner:EmitSound(self.Sound)
Owner:ViewPunch(Angle(-10, math.Round(util.SharedRandom("DarkRP_DoorRam" .. self:EntIndex() .. "_" .. self:GetTotalUsedMagCount(), -5, 5)), 0))
end
function SWEP:SecondaryAttack()
if CLIENT then self.LastIron = CurTime() end
self:SetNextSecondaryFire(CurTime() + 0.30)
self:SetIronsights(not self:GetIronsights())
if self:GetIronsights() then
self:SetHoldType("rpg")
else
self:SetHoldType("normal")
end
end
function SWEP:GetViewModelPosition(pos, ang)
local Mul = 1
if self.LastIron > CurTime() - 0.25 then
Mul = math.Clamp((CurTime() - self.LastIron) / 0.25, 0, 1)
end
if self:GetIronsights() then
Mul = 1-Mul
end
ang:RotateAroundAxis(ang:Right(), - 15 * Mul)
return pos,ang
end
DarkRP.hookStub{
name = "canDoorRam",
description = "Called when a player attempts to ram something. Use this to override ram behaviour or to disallow ramming.",
parameters = {
{
name = "ply",
description = "The player using the door ram.",
type = "Player"
},
{
name = "trace",
description = "The trace containing information about the hit position and ram entity.",
type = "table"
},
{
name = "ent",
description = "Short for the entity that is about to be hit by the door ram.",
type = "Entity"
}
},
returns = {
{
name = "override",
description = "Return true to override behaviour, false to disallow ramming and nil (or no value) to defer the decision.",
type = "boolean"
}
},
realm = "Shared"
}
if SERVER then
DarkRP.hookStub{
name = "onDoorRamUsed",
description = "Called when the door ram has been used.",
parameters = {
{
name = "success",
description = "Whether the door ram has been successful in ramming.",
type = "boolean"
},
{
name = "ply",
description = "The player that used the door ram.",
type = "Player"
},
{
name = "trace",
description = "The trace containing information about the hit position and ram entity.",
type = "table"
}
},
returns = {
}
}
end
hook.Add("SetupMove", "DarkRP_DoorRamJump", function(ply, mv)
local wep = ply:GetActiveWeapon()
if not wep:IsValid() or wep:GetClass() ~= "door_ram" or not wep.GetIronsights or not wep:GetIronsights() then return end
mv:SetButtons(bit.band(mv:GetButtons(), bit.bnot(IN_JUMP)))
end)

View File

@@ -0,0 +1,54 @@
TOOL.Category = "Falco Prop Protection"
TOOL.Name = "Share props"
TOOL.Command = nil
TOOL.ConfigName = ""
function TOOL:RightClick(trace)
local ent = trace.Entity
if not IsValid(ent) or CLIENT then return true end
ent.SharePhysgun1 = nil
ent.ShareGravgun1 = nil
ent.SharePlayerUse1 = nil
ent.ShareEntityDamage1 = nil
ent.ShareToolgun1 = nil
ent.AllowedPlayers = nil
return true
end
function TOOL:LeftClick(trace)
local ent = trace.Entity
if not IsValid(ent) or CLIENT then return true end
local ply = self:GetOwner()
local Physgun = ent.SharePhysgun1 or false
local GravGun = ent.ShareGravgun1 or false
local PlayerUse = ent.SharePlayerUse1 or false
local Damage = ent.ShareEntityDamage1 or false
local Toolgun = ent.ShareToolgun1 or false
-- This big usermessage will be too big if you select 63 players, since that will not happen I can't be arsed to solve it
umsg.Start("FPP_ShareSettings", ply)
umsg.Entity(ent)
umsg.Bool(Physgun)
umsg.Bool(GravGun)
umsg.Bool(PlayerUse)
umsg.Bool(Damage)
umsg.Bool(Toolgun)
if ent.AllowedPlayers then
umsg.Long(#ent.AllowedPlayers)
for k,v in pairs(ent.AllowedPlayers) do
umsg.Entity(v)
end
end
umsg.End()
return true
end
if CLIENT then
language.Add("Tool.shareprops.name", "Share tool")
language.Add("Tool.shareprops.desc", "Change sharing settings per prop")
language.Add("Tool.shareprops.0", "Left click: shares a prop. Right click unshares a prop")
end

View File

@@ -0,0 +1,210 @@
local function AddButtonToFrame(Frame)
Frame:SetTall(Frame:GetTall() + 110)
local button = vgui.Create("DButton", Frame)
button:SetPos(10, Frame:GetTall() - 110)
button:SetSize(180, 100)
Frame.buttonCount = (Frame.buttonCount or 0) + 1
Frame.lastButton = button
return button
end
DarkRP.stub{
name = "openKeysMenu",
description = "Open the keys/F2 menu.",
parameters = {},
realm = "Client",
returns = {},
metatable = DarkRP
}
DarkRP.hookStub{
name = "onKeysMenuOpened",
description = "Called when the keys menu is opened.",
parameters = {
{
name = "ent",
description = "The door entity.",
type = "Entity"
},
{
name = "Frame",
description = "The keys menu frame.",
type = "Panel"
}
},
returns = {
},
realm = "Client"
}
local KeyFrameVisible = false
local function openMenu(setDoorOwnerAccess, doorSettingsAccess)
if KeyFrameVisible then return end
local trace = LocalPlayer():GetEyeTrace()
local ent = trace.Entity
-- Don't open the menu if the entity is not ownable, the entity is too far away or the door settings are not loaded yet
if not IsValid(ent) or not ent:isKeysOwnable() or trace.HitPos:DistToSqr(LocalPlayer():EyePos()) > 40000 then return end
KeyFrameVisible = true
local Frame = vgui.Create("DFrame")
Frame:SetSize(200, 30) -- Base size
Frame.btnMaxim:SetVisible(false)
Frame.btnMinim:SetVisible(false)
Frame:SetVisible(true)
Frame:MakePopup()
Frame:ParentToHUD()
function Frame:Think()
local tr = LocalPlayer():GetEyeTrace()
local LAEnt = tr.Entity
if not IsValid(LAEnt) or not LAEnt:isKeysOwnable() or tr.HitPos:DistToSqr(LocalPlayer():EyePos()) > 40000 then
self:Close()
end
if not self.Dragging then return end
local x = gui.MouseX() - self.Dragging[1]
local y = gui.MouseY() - self.Dragging[2]
x = math.Clamp(x, 0, ScrW() - self:GetWide())
y = math.Clamp(y, 0, ScrH() - self:GetTall())
self:SetPos(x, y)
end
local entType = DarkRP.getPhrase(ent:IsVehicle() and "vehicle" or "door")
Frame:SetTitle(DarkRP.getPhrase("x_options", entType:gsub("^%a", string.upper)))
function Frame:Close()
KeyFrameVisible = false
self:SetVisible(false)
self:Remove()
end
-- All the buttons
if ent:isKeysOwnedBy(LocalPlayer()) then
local Owndoor = AddButtonToFrame(Frame)
Owndoor:SetText(DarkRP.getPhrase("sell_x", entType))
Owndoor.DoClick = function() RunConsoleCommand("darkrp", "toggleown") Frame:Close() end
local AddOwner = AddButtonToFrame(Frame)
AddOwner:SetText(DarkRP.getPhrase("add_owner"))
AddOwner.DoClick = function()
local menu = DermaMenu()
menu.found = false
for _, v in ipairs(DarkRP.nickSortedPlayers()) do
if not ent:isKeysOwnedBy(v) and not ent:isKeysAllowedToOwn(v) then
local steamID = v:SteamID()
menu.found = true
menu:AddOption(v:Nick(), function() RunConsoleCommand("darkrp", "ao", steamID) end)
end
end
if not menu.found then
menu:AddOption(DarkRP.getPhrase("noone_available"), function() end)
end
menu:Open()
end
local RemoveOwner = AddButtonToFrame(Frame)
RemoveOwner:SetText(DarkRP.getPhrase("remove_owner"))
RemoveOwner.DoClick = function()
local menu = DermaMenu()
for _, v in ipairs(DarkRP.nickSortedPlayers()) do
if (ent:isKeysOwnedBy(v) and not ent:isMasterOwner(v)) or ent:isKeysAllowedToOwn(v) then
local steamID = v:SteamID()
menu.found = true
menu:AddOption(v:Nick(), function() RunConsoleCommand("darkrp", "ro", steamID) end)
end
end
if not menu.found then
menu:AddOption(DarkRP.getPhrase("noone_available"), function() end)
end
menu:Open()
end
if not ent:isMasterOwner(LocalPlayer()) then
RemoveOwner:SetDisabled(true)
end
end
if doorSettingsAccess then
local DisableOwnage = AddButtonToFrame(Frame)
DisableOwnage:SetText(DarkRP.getPhrase(ent:getKeysNonOwnable() and "allow_ownership" or "disallow_ownership"))
DisableOwnage.DoClick = function() Frame:Close() RunConsoleCommand("darkrp", "toggleownable") end
end
if doorSettingsAccess and (ent:isKeysOwned() or ent:getKeysNonOwnable() or ent:getKeysDoorGroup() or hasTeams) or ent:isKeysOwnedBy(LocalPlayer()) then
local DoorTitle = AddButtonToFrame(Frame)
DoorTitle:SetText(DarkRP.getPhrase("set_x_title", entType))
DoorTitle.DoClick = function()
Derma_StringRequest(DarkRP.getPhrase("set_x_title", entType), DarkRP.getPhrase("set_x_title_long", entType), "", function(text)
RunConsoleCommand("darkrp", "title", text)
if IsValid(Frame) then
Frame:Close()
end
end,
function() end, DarkRP.getPhrase("ok"), DarkRP.getPhrase("cancel"))
end
end
if not ent:isKeysOwned() and not ent:getKeysNonOwnable() and not ent:getKeysDoorGroup() and not ent:getKeysDoorTeams() or not ent:isKeysOwnedBy(LocalPlayer()) and ent:isKeysAllowedToOwn(LocalPlayer()) then
local Owndoor = AddButtonToFrame(Frame)
Owndoor:SetText(DarkRP.getPhrase("buy_x", entType))
Owndoor.DoClick = function() RunConsoleCommand("darkrp", "toggleown") Frame:Close() end
end
if doorSettingsAccess then
local EditDoorGroups = AddButtonToFrame(Frame)
EditDoorGroups:SetText(DarkRP.getPhrase("edit_door_group"))
EditDoorGroups.DoClick = function()
local menu = DermaMenu()
local groups = menu:AddSubMenu(DarkRP.getPhrase("door_groups"))
local teams = menu:AddSubMenu(DarkRP.getPhrase("jobs"))
local add = teams:AddSubMenu(DarkRP.getPhrase("add"))
local remove = teams:AddSubMenu(DarkRP.getPhrase("remove"))
menu:AddOption(DarkRP.getPhrase("none"), function()
RunConsoleCommand("darkrp", "togglegroupownable")
if IsValid(Frame) then Frame:Close() end
end)
for k in pairs(RPExtraTeamDoors) do
groups:AddOption(k, function()
RunConsoleCommand("darkrp", "togglegroupownable", k)
if IsValid(Frame) then Frame:Close() end
end)
end
local doorTeams = ent:getKeysDoorTeams()
for k, v in pairs(RPExtraTeams) do
local which = (not doorTeams or not doorTeams[k]) and add or remove
which:AddOption(v.name, function()
RunConsoleCommand("darkrp", "toggleteamownable", k)
if IsValid(Frame) then Frame:Close() end
end)
end
menu:Open()
end
end
if Frame.buttonCount == 1 then
Frame.lastButton:DoClick()
elseif Frame.buttonCount == 0 or not Frame.buttonCount then
Frame:Close()
KeyFrameVisible = true
timer.Simple(0.3, function() KeyFrameVisible = false end)
end
hook.Call("onKeysMenuOpened", nil, ent, Frame)
Frame:Center()
Frame:SetSkin(GAMEMODE.Config.DarkRPSkin)
end
function DarkRP.openKeysMenu(um)
CAMI.PlayerHasAccess(LocalPlayer(), "DarkRP_SetDoorOwner", function(setDoorOwnerAccess)
CAMI.PlayerHasAccess(LocalPlayer(), "DarkRP_ChangeDoorSettings", fp{openMenu, setDoorOwnerAccess})
end)
end
usermessage.Hook("KeysMenu", DarkRP.openKeysMenu)

View File

@@ -0,0 +1,163 @@
AddCSLuaFile()
if SERVER then
AddCSLuaFile("cl_menu.lua")
end
if CLIENT then
SWEP.Slot = 1
SWEP.SlotPos = 1
SWEP.DrawAmmo = false
SWEP.DrawCrosshair = false
include("cl_menu.lua")
end
SWEP.PrintName = "Keys"
SWEP.Author = "DarkRP Developers"
SWEP.Instructions = "Left click to lock\nRight click to unlock\nReload for door settings or animation menu"
SWEP.Contact = ""
SWEP.Purpose = ""
SWEP.IsDarkRPKeys = true
SWEP.WorldModel = ""
SWEP.ViewModelFOV = 62
SWEP.ViewModelFlip = false
SWEP.AnimPrefix = "rpg"
SWEP.UseHands = true
SWEP.Spawnable = true
SWEP.AdminOnly = true
SWEP.Category = "DarkRP (Utility)"
SWEP.Sound = "doors/door_latch3.wav"
SWEP.Primary.Delay = 0.3
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = 0
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = ""
SWEP.Secondary.Delay = 0.3
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = 0
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = ""
function SWEP:Initialize()
self:SetHoldType("normal")
end
function SWEP:Deploy()
if CLIENT or not IsValid(self:GetOwner()) then return true end
self:GetOwner():DrawWorldModel(false)
return true
end
function SWEP:Holster()
return true
end
function SWEP:PreDrawViewModel()
return true
end
local function lookingAtLockable(ply, ent, hitpos)
local eyepos = ply:EyePos()
return IsValid(ent)
and ent:isKeysOwnable()
and (
ent:isDoor() and eyepos:DistToSqr(hitpos) < 2000
or
ent:IsVehicle() and eyepos:DistToSqr(hitpos) < 4000
)
end
local function lockUnlockAnimation(ply, snd)
ply:EmitSound("npc/metropolice/gear" .. math.random(1, 6) .. ".wav")
timer.Simple(0.9, function() if IsValid(ply) then ply:EmitSound(snd) end end)
umsg.Start("anim_keys")
umsg.Entity(ply)
umsg.String("usekeys")
umsg.End()
ply:AnimRestartGesture(GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_GMOD_GESTURE_ITEM_PLACE, true)
end
local function doKnock(ply, sound)
ply:EmitSound(sound, 100, math.random(90, 110))
umsg.Start("anim_keys")
umsg.Entity(ply)
umsg.String("knocking")
umsg.End()
ply:AnimRestartGesture(GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_HL2MP_GESTURE_RANGE_ATTACK_FIST, true)
end
function SWEP:PrimaryAttack()
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
local trace = Owner:GetEyeTrace()
local ent = trace.Entity
if not lookingAtLockable(Owner, ent, trace.HitPos) then return end
self:SetNextPrimaryFire(CurTime() + self.Primary.Delay)
if CLIENT then return end
if Owner:canKeysLock(ent) then
ent:keysLock() -- Lock the door immediately so it won't annoy people
lockUnlockAnimation(Owner, self.Sound)
elseif ent:IsVehicle() then
DarkRP.notify(Owner, 1, 3, DarkRP.getPhrase("do_not_own_ent"))
else
doKnock(Owner, "physics/wood/wood_crate_impact_hard2.wav")
end
end
function SWEP:SecondaryAttack()
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
local trace = Owner:GetEyeTrace()
local ent = trace.Entity
if not lookingAtLockable(Owner, ent, trace.HitPos) then return end
self:SetNextSecondaryFire(CurTime() + self.Secondary.Delay)
if CLIENT then return end
if Owner:canKeysUnlock(ent) then
ent:keysUnLock() -- Unlock the door immediately so it won't annoy people
lockUnlockAnimation(Owner, self.Sound)
elseif ent:IsVehicle() then
DarkRP.notify(Owner, 1, 3, DarkRP.getPhrase("do_not_own_ent"))
else
doKnock(Owner, "physics/wood/wood_crate_impact_hard3.wav")
end
end
function SWEP:Reload()
local trace = self:GetOwner():GetEyeTrace()
local ent = trace.Entity
if not IsValid(ent) or ((not ent:isDoor() and not ent:IsVehicle()) or self:GetOwner():EyePos():DistToSqr(trace.HitPos) > 40000) then
if CLIENT and not DarkRP.disabledDefaults["modules"]["animations"] then RunConsoleCommand("_DarkRP_AnimationMenu") end
return
end
if SERVER then
umsg.Start("KeysMenu", self:GetOwner())
umsg.End()
end
end

View File

@@ -0,0 +1,309 @@
AddCSLuaFile()
if CLIENT then
SWEP.Slot = 5
SWEP.SlotPos = 1
SWEP.DrawAmmo = false
SWEP.DrawCrosshair = false
end
-- Variables that are used on both client and server
SWEP.PrintName = "Lock Pick"
SWEP.Author = "DarkRP Developers"
SWEP.Instructions = "Left or right click to pick a lock"
SWEP.Contact = ""
SWEP.Purpose = ""
SWEP.IsDarkRPLockpick = true
SWEP.ViewModelFOV = 62
SWEP.ViewModelFlip = false
SWEP.ViewModel = Model("models/weapons/c_crowbar.mdl")
SWEP.WorldModel = Model("models/weapons/w_crowbar.mdl")
SWEP.UseHands = true
SWEP.Spawnable = true
SWEP.AdminOnly = true
SWEP.Category = "DarkRP (Utility)"
SWEP.Sound = Sound("physics/wood/wood_box_impact_hard3.wav")
SWEP.Primary.ClipSize = -1 -- Size of a clip
SWEP.Primary.DefaultClip = 0 -- Default number of bullets in a clip
SWEP.Primary.Automatic = false -- Automatic/Semi Auto
SWEP.Primary.Ammo = ""
SWEP.Secondary.ClipSize = -1 -- Size of a clip
SWEP.Secondary.DefaultClip = -1 -- Default number of bullets in a clip
SWEP.Secondary.Automatic = false -- Automatic/Semi Auto
SWEP.Secondary.Ammo = ""
function SWEP:SetupDataTables()
self:NetworkVar("Bool", 0, "IsLockpicking")
self:NetworkVar("Float", 0, "LockpickStartTime")
self:NetworkVar("Float", 1, "LockpickEndTime")
self:NetworkVar("Float", 2, "NextSoundTime")
self:NetworkVar("Int", 0, "TotalLockpicks")
self:NetworkVar("Entity", 0, "LockpickEnt")
end
function SWEP:Initialize()
self:SetHoldType("normal")
end
function SWEP:PrimaryAttack()
self:SetNextPrimaryFire(CurTime() + 0.5)
if self:GetIsLockpicking() then return end
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
Owner:LagCompensation(true)
local trace = Owner:GetEyeTrace()
Owner:LagCompensation(false)
local ent = trace.Entity
if not IsValid(ent) or ent.DarkRPCanLockpick == false then return end
local canLockpick = hook.Call("canLockpick", nil, Owner, ent, trace)
if canLockpick == false then return end
if canLockpick ~= true and (
trace.HitPos:DistToSqr(Owner:GetShootPos()) > 10000 or
(not GAMEMODE.Config.canforcedooropen and ent:getKeysNonOwnable()) or
(not ent:isDoor() and not ent:IsVehicle() and not string.find(string.lower(ent:GetClass()), "vehicle") and (not GAMEMODE.Config.lockpickfading or not ent.isFadingDoor))
) then
return
end
self:SetHoldType("pistol")
self:SetIsLockpicking(true)
self:SetLockpickEnt(ent)
self:SetLockpickStartTime(CurTime())
local endDelta = hook.Call("lockpickTime", nil, Owner, ent) or util.SharedRandom("DarkRP_Lockpick" .. self:EntIndex() .. "_" .. self:GetTotalLockpicks(), 10, 30)
self:SetLockpickEndTime(CurTime() + endDelta)
self:SetTotalLockpicks(self:GetTotalLockpicks() + 1)
if IsFirstTimePredicted() then
hook.Call("lockpickStarted", nil, Owner, ent, trace)
end
if CLIENT then
self.Dots = ""
self.NextDotsTime = SysTime() + 0.5
return
end
local onFail = function(ply) if ply == Owner then hook.Call("onLockpickCompleted", nil, ply, false, ent) end end
-- Lockpick fails when dying or disconnecting
hook.Add("PlayerDeath", self, fc{onFail, fn.Flip(fn.Const)})
hook.Add("PlayerDisconnected", self, fc{onFail, fn.Flip(fn.Const)})
-- Remove hooks when finished
hook.Add("onLockpickCompleted", self, fc{fp{hook.Remove, "PlayerDisconnected", self}, fp{hook.Remove, "PlayerDeath", self}})
end
function SWEP:Holster()
if self:GetIsLockpicking() and self:GetLockpickEndTime() ~= 0 then
self:Fail()
end
return true
end
function SWEP:Succeed()
self:SetHoldType("normal")
local ent = self:GetLockpickEnt()
self:SetIsLockpicking(false)
self:SetLockpickEnt(nil)
if not IsValid(ent) then return end
local override = hook.Call("onLockpickCompleted", nil, self:GetOwner(), true, ent)
if override then return end
if ent.isFadingDoor and ent.fadeActivate and not ent.fadeActive then
ent:fadeActivate()
if IsFirstTimePredicted() then timer.Simple(5, function() if IsValid(ent) and ent.fadeActive then ent:fadeDeactivate() end end) end
elseif ent.Fire then
ent:keysUnLock()
ent:Fire("open", "", .6)
ent:Fire("setanimation", "open", .6)
end
end
function SWEP:Fail()
self:SetIsLockpicking(false)
self:SetHoldType("normal")
hook.Call("onLockpickCompleted", nil, self:GetOwner(), false, self:GetLockpickEnt())
self:SetLockpickEnt(nil)
end
local colorBackground = Color(10, 10, 10, 120)
local dots = {
[0] = ".",
[1] = "..",
[2] = "...",
[3] = ""
}
function SWEP:Think()
if not self:GetIsLockpicking() or self:GetLockpickEndTime() == 0 then return end
if CurTime() >= self:GetNextSoundTime() then
self:SetNextSoundTime(CurTime() + 1)
local snd = {1,3,4}
self:EmitSound("weapons/357/357_reload" .. tostring(snd[math.Round(util.SharedRandom("DarkRP_LockpickSnd" .. CurTime(), 1, #snd))]) .. ".wav", 50, 100)
end
if CLIENT and (not self.NextDotsTime or SysTime() >= self.NextDotsTime) then
self.NextDotsTime = SysTime() + 0.5
self.Dots = self.Dots or ""
local len = string.len(self.Dots)
self.Dots = dots[len]
end
local trace = self:GetOwner():GetEyeTrace()
if not IsValid(trace.Entity) or trace.Entity ~= self:GetLockpickEnt() or trace.HitPos:DistToSqr(self:GetOwner():GetShootPos()) > 10000 then
self:Fail()
elseif self:GetLockpickEndTime() <= CurTime() then
self:Succeed()
end
end
function SWEP:DrawHUD()
if not self:GetIsLockpicking() or self:GetLockpickEndTime() == 0 then return end
self.Dots = self.Dots or ""
local w = ScrW()
local h = ScrH()
local x, y, width, height = w / 2 - w / 10, h / 2 - 60, w / 5, h / 15
draw.RoundedBox(8, x, y, width, height, colorBackground)
local time = self:GetLockpickEndTime() - self:GetLockpickStartTime()
local curtime = CurTime() - self:GetLockpickStartTime()
local status = math.Clamp(curtime / time, 0, 1)
local BarWidth = status * (width - 16)
local cornerRadius = math.Min(8, BarWidth / 3 * 2 - BarWidth / 3 * 2 % 2)
draw.RoundedBox(cornerRadius, x + 8, y + 8, BarWidth, height - 16, Color(255 - (status * 255), 0 + (status * 255), 0, 255))
draw.DrawNonParsedSimpleText(DarkRP.getPhrase("picking_lock") .. self.Dots, "Trebuchet24", w / 2, y + height / 2, color_white, 1, 1)
end
function SWEP:SecondaryAttack()
self:PrimaryAttack()
end
DarkRP.hookStub{
name = "canLockpick",
description = "Whether an entity can be lockpicked.",
parameters = {
{
name = "ply",
description = "The player attempting to lockpick an entity.",
type = "Player"
},
{
name = "ent",
description = "The entity being lockpicked.",
type = "Entity"
},
{
name = "trace",
description = "The trace result.",
type = "table"
}
},
returns = {
{
name = "allowed",
description = "Whether the entity can be lockpicked",
type = "boolean"
}
},
realm = "Shared"
}
DarkRP.hookStub{
name = "lockpickStarted",
description = "Called when a player is about to pick a lock.",
parameters = {
{
name = "ply",
description = "The player that is about to pick a lock.",
type = "Player"
},
{
name = "ent",
description = "The entity being lockpicked.",
type = "Entity"
},
{
name = "trace",
description = "The trace result.",
type = "table"
}
},
returns = {},
realm = "Shared"
}
DarkRP.hookStub{
name = "onLockpickCompleted",
description = "Result of a player attempting to lockpick an entity.",
parameters = {
{
name = "ply",
description = "The player attempting to lockpick the entity.",
type = "Player"
},
{
name = "success",
description = "Whether the player succeeded in lockpicking the entity.",
type = "boolean"
},
{
name = "ent",
description = "The entity that was lockpicked.",
type = "Entity"
},
},
returns = {
{
name = "override",
description = "Return true to override default behaviour, which is opening the (fading) door.",
type = "boolean"
}
},
realm = "Shared"
}
DarkRP.hookStub{
name = "lockpickTime",
description = "The length of time, in seconds, it takes to lockpick an entity.",
parameters = {
{
name = "ply",
description = "The player attempting to lockpick an entity.",
type = "Player"
},
{
name = "ent",
description = "The entity being lockpicked.",
type = "Entity"
},
},
returns = {
{
name = "time",
description = "Seconds in which it takes a player to lockpick an entity",
type = "number"
}
},
realm = "Shared"
}

View File

@@ -0,0 +1,17 @@
include("shared.lua")
local deltas = {-44, -34, -24, -14, 44, 34, 24, 14}
function SWEP:DrawHUD()
if self:GetScopeLevel() < 2 then return end
--Width hairs
draw.RoundedBox(1, ScrW() / 2 - 54, ScrH() / 2, 50, 1, color_black)
draw.RoundedBox(1, ScrW() / 2 + 4, ScrH() / 2, 50, 1, color_black)
draw.RoundedBox(1, ScrW() / 2, ScrH() / 2 - 54, 1, 50, color_black)
draw.RoundedBox(1, ScrW() / 2, ScrH() / 2 + 4, 1, 50, color_black)
for _, v in ipairs(deltas) do
draw.RoundedBox(1, ScrW() / 2 + v, ScrH() / 2 - 5, 1, 11, color_black)
draw.RoundedBox(1, ScrW() / 2 - 5, ScrH() / 2 + v, 11, 1, color_black)
end
end

View File

@@ -0,0 +1,84 @@
AddCSLuaFile()
if SERVER then
AddCSLuaFile("cl_init.lua")
end
if CLIENT then
SWEP.Author = "DarkRP Developers"
SWEP.Slot = 0
SWEP.SlotPos = 0
SWEP.IconLetter = "n"
killicon.AddFont("ls_sniper", "CSKillIcons", SWEP.IconLetter, Color(200, 200, 200, 255))
end
DEFINE_BASECLASS("weapon_cs_base2")
SWEP.PrintName = "Silenced Sniper"
SWEP.Spawnable = true
SWEP.AdminOnly = false
SWEP.Category = "DarkRP (Weapon)"
SWEP.ViewModel = "models/weapons/cstrike/c_snip_g3sg1.mdl"
SWEP.WorldModel = "models/weapons/w_snip_g3sg1.mdl"
SWEP.Weight = 3
SWEP.HoldType = "ar2"
SWEP.LoweredHoldType = "passive"
SWEP.Primary.Sound = Sound("Weapon_M4A1.Silenced")
SWEP.Primary.Damage = 100
SWEP.Primary.Recoil = 0.03
SWEP.Primary.NumShots = 1
SWEP.Primary.Cone = 0.0001 - .05
SWEP.Primary.ClipSize = 25
SWEP.Primary.Delay = 0.7
SWEP.Primary.DefaultClip = 75
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "smg1"
SWEP.IronSightsPos = Vector(0, 0, 0) -- this is just to make it disappear so it doesn't show up whilst scoped
function SWEP:SetupDataTables()
BaseClass.SetupDataTables(self)
-- Int 0 = BurstBulletNum
-- Int 1 = TotalUsedMagCount
self:NetworkVar("Int", 2, "ScopeLevel")
end
function SWEP:Deploy()
self:GetOwner():SetFOV(0, 0)
self:SetScopeLevel(0)
return BaseClass.Deploy(self)
end
function SWEP:Holster()
self:GetOwner():SetFOV(0, 0)
self:SetScopeLevel(0)
return BaseClass.Holster(self)
end
local zoomFOV = {0, 0, 25, 5}
function SWEP:SecondaryAttack()
if not self.IronSightsPos then return end
self:SetNextSecondaryFire(CurTime() + 0.1)
self:SetScopeLevel((self:GetScopeLevel() + 1) % 4)
self:SetIronsights(self:GetScopeLevel() > 0)
self:GetOwner():SetFOV(zoomFOV[self:GetScopeLevel() + 1], 0)
end
function SWEP:Reload()
self:GetOwner():SetFOV(0, 0)
self:SetScopeLevel(0)
return BaseClass.Reload(self)
end

View File

@@ -0,0 +1,81 @@
if SERVER then
AddCSLuaFile("shared.lua")
end
SWEP.PrintName = "Medic Kit"
SWEP.Author = "DarkRP Developers"
SWEP.Slot = 4
SWEP.SlotPos = 0
SWEP.Description = "Heals the wounded."
SWEP.Contact = ""
SWEP.Purpose = ""
SWEP.Instructions = "Left click to heal someone\nRight click to heal yourself"
SWEP.IsDarkRPMedKit = true
SWEP.Spawnable = true
SWEP.AdminOnly = true
SWEP.Category = "DarkRP (Utility)"
SWEP.ViewModel = "models/weapons/c_medkit.mdl"
SWEP.WorldModel = "models/weapons/w_medkit.mdl"
SWEP.UseHands = true
SWEP.Primary.Recoil = 0
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = 1
SWEP.Primary.Automatic = true
SWEP.Primary.Delay = 0.1
SWEP.Primary.Ammo = "none"
SWEP.Secondary.Recoil = 0
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = 1
SWEP.Secondary.Automatic = true
SWEP.Secondary.Delay = 0.3
SWEP.Secondary.Ammo = "none"
function SWEP:PrimaryAttack()
self:SetNextPrimaryFire(CurTime() + self.Primary.Delay)
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
local found
local lastDot = -1 -- the opposite of what you're looking at
Owner:LagCompensation(true)
local aimVec = Owner:GetAimVector()
local shootPos = Owner:GetShootPos()
for _, v in ipairs(player.GetAll()) do
local maxhealth = v:GetMaxHealth() or 100
local targetShootPos = v:GetShootPos()
if v == Owner or targetShootPos:DistToSqr(shootPos) > 7225 or v:Health() >= maxhealth or not v:Alive() then continue end
local direction = targetShootPos - shootPos
direction:Normalize()
local dot = direction:Dot(aimVec)
-- Looking more in the direction of this player
if dot > lastDot then
lastDot = dot
found = v
end
end
Owner:LagCompensation(false)
if found then
found:SetHealth(found:Health() + 1)
self:EmitSound("hl1/fvox/boop.wav", 150, math.max(found:Health() / found:GetMaxHealth() * 100, 25), 1, CHAN_AUTO)
end
end
function SWEP:SecondaryAttack()
self:SetNextSecondaryFire(CurTime() + self.Secondary.Delay)
local ply = self:GetOwner()
local maxhealth = ply:GetMaxHealth() or 100
if ply:Health() < maxhealth then
ply:SetHealth(ply:Health() + 1)
self:EmitSound("hl1/fvox/boop.wav", 150, math.max(ply:Health() / ply:GetMaxHealth() * 100, 25), 1, CHAN_AUTO)
end
end

View File

@@ -0,0 +1,128 @@
local meta = FindMetaTable("Player")
local pocket = {}
local frame
local reload
--[[---------------------------------------------------------------------------
Stubs
---------------------------------------------------------------------------]]
DarkRP.stub{
name = "openPocketMenu",
description = "Open the DarkRP pocket menu.",
realm = "Client",
parameters = {
},
returns = {
},
metatable = DarkRP
}
--[[---------------------------------------------------------------------------
Interface functions
---------------------------------------------------------------------------]]
function meta:getPocketItems()
if self ~= LocalPlayer() then return nil end
return pocket
end
function DarkRP.openPocketMenu()
if IsValid(frame) and frame:IsVisible() then return end
local wep = LocalPlayer():GetActiveWeapon()
if not wep:IsValid() or wep:GetClass() ~= "pocket" then return end
if not pocket then
pocket = {}
return
end
if table.IsEmpty(pocket) then return end
frame = vgui.Create("DFrame")
local count = GAMEMODE.Config.pocketitems or GM.Config.pocketitems
frame:SetSize(345, 32 + 64 * math.ceil(count / 5) + 3 * math.ceil(count / 5))
frame:SetTitle(DarkRP.getPhrase("drop_item"))
frame.btnMaxim:SetVisible(false)
frame.btnMinim:SetVisible(false)
frame:SetDraggable(false)
frame:MakePopup()
frame:Center()
local Scroll = vgui.Create("DScrollPanel", frame)
Scroll:Dock(FILL)
local sbar = Scroll:GetVBar()
sbar:SetWide(3)
frame.List = vgui.Create("DIconLayout", Scroll)
frame.List:Dock(FILL)
frame.List:SetSpaceY(3)
frame.List:SetSpaceX(3)
reload()
frame:SetSkin(GAMEMODE.Config.DarkRPSkin)
end
net.Receive("DarkRP_PocketMenu", DarkRP.openPocketMenu)
--[[---------------------------------------------------------------------------
UI
---------------------------------------------------------------------------]]
function reload()
if not IsValid(frame) or not frame:IsVisible() then return end
if not pocket or next(pocket) == nil then frame:Close() return end
local itemCount = table.Count(pocket)
frame.List:Clear()
local items = {}
for k, v in pairs(pocket) do
local ListItem = frame.List:Add("DPanel")
ListItem:SetSize(64, 64)
local icon = vgui.Create("SpawnIcon", ListItem)
icon:SetModel(v.model)
icon:SetSize(64, 64)
icon:SetTooltip()
icon.DoClick = function(self)
icon:SetTooltip()
net.Start("DarkRP_spawnPocket")
net.WriteFloat(k)
net.SendToServer()
pocket[k] = nil
itemCount = itemCount - 1
if itemCount == 0 then
frame:Close()
return
end
fn.Map(self.Remove, items)
items = {}
local wep = LocalPlayer():GetActiveWeapon()
wep:SetHoldType("pistol")
timer.Simple(0.2, function()
if wep:IsValid() then
wep:SetHoldType("normal")
end
end)
end
table.insert(items, icon)
end
if itemCount < GAMEMODE.Config.pocketitems then
for _ = 1, GAMEMODE.Config.pocketitems - itemCount do
local ListItem = frame.List:Add("DPanel")
ListItem:SetSize(64, 64)
end
end
end
local function retrievePocket()
pocket = net.ReadTable()
reload()
end
net.Receive("DarkRP_Pocket", retrievePocket)

View File

@@ -0,0 +1,146 @@
AddCSLuaFile()
if SERVER then
AddCSLuaFile("cl_menu.lua")
include("sv_init.lua")
end
if CLIENT then
include("cl_menu.lua")
end
SWEP.PrintName = "Pocket"
SWEP.Slot = 1
SWEP.SlotPos = 1
SWEP.DrawAmmo = false
SWEP.DrawCrosshair = true
SWEP.Base = "weapon_cs_base2"
SWEP.Author = "DarkRP Developers"
SWEP.Instructions = "Left click to pick up\nRight click to drop\nReload to open the menu"
SWEP.Contact = ""
SWEP.Purpose = ""
SWEP.IsDarkRPPocket = true
SWEP.IconLetter = ""
SWEP.ViewModelFOV = 62
SWEP.ViewModelFlip = false
SWEP.AnimPrefix = "rpg"
SWEP.WorldModel = ""
SWEP.Spawnable = true
SWEP.AdminOnly = true
SWEP.Category = "DarkRP (Utility)"
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = 0
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = ""
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = 0
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = ""
function SWEP:Initialize()
self:SetHoldType("normal")
end
function SWEP:Deploy()
return true
end
function SWEP:DrawWorldModel() end
function SWEP:PreDrawViewModel(vm)
return true
end
function SWEP:Holster()
if not SERVER then return true end
local Owner = self:GetOwner()
Owner:DrawViewModel(true)
Owner:DrawWorldModel(true)
return true
end
function SWEP:PrimaryAttack()
self:SetNextPrimaryFire(CurTime() + 0.2)
if not SERVER then return end
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
local ent = Owner:GetEyeTrace().Entity
local canPickup, message = hook.Call("canPocket", GAMEMODE, Owner, ent)
if not canPickup then
if message then DarkRP.notify(Owner, 1, 4, message) end
return
end
Owner:addPocketItem(ent)
end
function SWEP:SecondaryAttack()
if not SERVER then return end
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
local maxK = 0
for k in pairs(Owner:getPocketItems()) do
if k < maxK then continue end
maxK = k
end
if maxK == 0 then
DarkRP.notify(Owner, 1, 4, DarkRP.getPhrase("pocket_no_items"))
return
end
if SERVER then
local canPickup, message = hook.Call("canDropPocketItem", nil, Owner, maxK, Owner.darkRPPocket[maxK])
if canPickup == false then
if message then DarkRP.notify(Owner, 1, 4, message) end
return
end
end
Owner:dropPocketItem(maxK)
end
function SWEP:Reload()
if CLIENT then
DarkRP.openPocketMenu()
end
if SERVER and game.SinglePlayer() then
net.Start("DarkRP_PocketMenu")
net.Send(self:GetOwner())
end
end
local meta = FindMetaTable("Player")
DarkRP.stub{
name = "getPocketItems",
description = "Get a player's pocket items.",
parameters = {
},
returns = {
{
name = "items",
description = "A table containing crucial information about the items in the pocket.",
type = "table"
}
},
metatable = meta,
realm = "Shared"
}

View File

@@ -0,0 +1,375 @@
local meta = FindMetaTable("Player")
--[[---------------------------------------------------------------------------
Stubs
---------------------------------------------------------------------------]]
DarkRP.stub{
name = "dropPocketItem",
description = "Make the player drop an item from the pocket.",
parameters = {
{
name = "ent",
description = "The entity to drop.",
type = "Entity",
optional = false
}
},
returns = {
},
metatable = meta
}
DarkRP.stub{
name = "addPocketItem",
description = "Add an item to the pocket of the player.",
parameters = {
{
name = "ent",
description = "The entity to add.",
type = "Entity",
optional = false
}
},
returns = {
},
metatable = meta
}
DarkRP.stub{
name = "removePocketItem",
description = "Remove an item from the pocket of the player.",
parameters = {
{
name = "item",
description = "The index of the entity to remove from pocket.",
type = "number",
optional = false
}
},
returns = {
},
metatable = meta
}
DarkRP.hookStub{
name = "canPocket",
description = "Whether a player can pocket a certain item.",
parameters = {
{
name = "ply",
description = "The player.",
type = "Player"
},
{
name = "item",
description = "The item to be pocketed.",
type = "Entity"
}
},
returns = {
{
name = "answer",
description = "Whether the entity can be pocketed.",
type = "boolean"
},
{
name = "message",
description = "The message to send to the player when the answer is false.",
type = "string"
}
}
}
DarkRP.hookStub{
name = "onPocketItemAdded",
description = "Called when an entity is added to the pocket.",
parameters = {
{
name = "ply",
description = "The pocket holder.",
type = "Player"
},
{
name = "ent",
description = "The entity.",
type = "Entity"
},
{
name = "serialized",
description = "The serialized version of the pocketed entity.",
type = "table"
}
},
returns = {
}
}
DarkRP.hookStub{
name = "canDropPocketItem",
description = "Whether someone is allowed to drop something from their pocket.",
parameters = {
{
name = "ply",
description = "The pocket holder.",
type = "Player"
},
{
name = "item",
description = "The pocket item's index in the pocket.",
type = "table"
},
{
name = "serialized",
description = "The pocket item.",
type = "table"
}
},
returns = {
{
name = "answer",
description = "Whether the item can be dropped.",
type = "boolean"
},
{
name = "message",
description = "The message to send to the player when the answer is false.",
type = "string"
}
}
}
DarkRP.hookStub{
name = "onPocketItemRemoved",
description = "Called when an item is removed from the pocket.",
parameters = {
{
name = "ply",
description = "The pocket holder.",
type = "Player"
},
{
name = "item",
description = "The index of the pocket item.",
type = "number"
}
},
returns = {
}
}
--[[---------------------------------------------------------------------------
Functions
---------------------------------------------------------------------------]]
-- workaround: GetNetworkVars doesn't give entities because the /duplicator/ doesn't want to save entities
local function getDTVars(ent)
if not ent.GetNetworkVars then return nil end
local name, value = debug.getupvalue(ent.GetNetworkVars, 1)
if name ~= "datatable" then
ErrorNoHalt("Warning: Datatable cannot be stored properly in pocket. Tell a developer!")
end
local res = {}
for k,v in pairs(value) do
res[k] = v.GetFunc(ent, v.index)
end
return res
end
local function serialize(ent)
local serialized = duplicator.CopyEntTable(ent)
serialized.DT = getDTVars(ent)
-- this function is also called in duplicator.CopyEntTable, but some
-- entities change the DT vars of a copied entity (e.g. Lexic's moneypot)
-- That is undone with the getDTVars function call.
-- Re-call OnEntityCopyTableFinish assuming its implementation is pure.
if ent.OnEntityCopyTableFinish then
ent:OnEntityCopyTableFinish(serialized)
end
return serialized
end
local function deserialize(ply, item)
local ent = ents.Create(item.Class)
duplicator.DoGeneric(ent, item)
ent:Spawn()
ent:Activate()
duplicator.DoGenericPhysics(ent, ply, item)
table.Merge(ent:GetTable(), item)
if ent:IsWeapon() and ent.Weapon ~= nil and not ent.Weapon:IsValid() then ent.Weapon = ent end
if ent.Entity ~= nil and not ent.Entity:IsValid() then ent.Entity = ent end
local trace = {}
trace.start = ply:EyePos()
trace.endpos = trace.start + ply:GetAimVector() * 85
trace.filter = ply
local tr = util.TraceLine(trace)
ent:SetPos(tr.HitPos)
DarkRP.placeEntity(ent, tr, ply)
local phys = ent:GetPhysicsObject()
timer.Simple(0, function() if phys:IsValid() then phys:Wake() end end)
if ent.OnDuplicated then
ent:OnDuplicated(item)
end
if ent.PostEntityPaste then
ent:PostEntityPaste(ply, ent, {ent})
end
return ent
end
local function dropAllPocketItems(ply)
for k in pairs(ply.darkRPPocket or {}) do
ply:dropPocketItem(k)
end
end
util.AddNetworkString("DarkRP_Pocket")
local function sendPocketItems(ply)
net.Start("DarkRP_Pocket")
net.WriteTable(ply:getPocketItems())
net.Send(ply)
end
util.AddNetworkString("DarkRP_PocketMenu")
--[[---------------------------------------------------------------------------
Interface functions
---------------------------------------------------------------------------]]
function meta:addPocketItem(ent)
if not IsValid(ent) then DarkRP.error("Entity not valid", 2) end
if ent.USED then return end
-- This item cannot be used until it has been removed
ent.USED = true
local serialized = serialize(ent)
hook.Call("onPocketItemAdded", nil, self, ent, serialized)
ent.IsPocketing = true
ent:Remove()
self.darkRPPocket = self.darkRPPocket or {}
local id = table.insert(self.darkRPPocket, serialized)
sendPocketItems(self)
return id
end
function meta:removePocketItem(item)
if not self.darkRPPocket or not self.darkRPPocket[item] then DarkRP.error("Player does not contain " .. item .. " in their pocket.", 2) end
hook.Call("onPocketItemRemoved", nil, self, item)
self.darkRPPocket[item] = nil
sendPocketItems(self)
end
function meta:dropPocketItem(item)
if not self.darkRPPocket or not self.darkRPPocket[item] then DarkRP.error("Player does not contain " .. item .. " in their pocket.", 2) end
local id = self.darkRPPocket[item]
local ent = deserialize(self, id)
-- reset USED status
ent.USED = nil
hook.Call("onPocketItemDropped", nil, self, ent, item, id)
self:removePocketItem(item)
return ent
end
-- serverside implementation
function meta:getPocketItems()
self.darkRPPocket = self.darkRPPocket or {}
local res = {}
for k, v in pairs(self.darkRPPocket) do
res[k] = {
model = v.Model,
class = v.Class
}
end
return res
end
--[[---------------------------------------------------------------------------
Commands
---------------------------------------------------------------------------]]
util.AddNetworkString("DarkRP_spawnPocket")
net.Receive("DarkRP_spawnPocket", function(len, ply)
local item = net.ReadFloat()
if not ply.darkRPPocket or not ply.darkRPPocket[item] then return end
local canPickup, message = hook.Call("canDropPocketItem", nil, ply, item, ply.darkRPPocket[item])
if canPickup == false then
if message then DarkRP.notify(ply, 1, 4, message) end
sendPocketItems(ply)
return
end
ply:dropPocketItem(item)
end)
--[[---------------------------------------------------------------------------
Hooks
---------------------------------------------------------------------------]]
function GAMEMODE:canPocket(ply, item)
if not IsValid(item) then return false end
local class = item:GetClass()
if item.Removed then return false, DarkRP.getPhrase("cannot_pocket_x") end
if not item:CPPICanPickup(ply) then return false, DarkRP.getPhrase("cannot_pocket_x") end
if item.jailWall then return false, DarkRP.getPhrase("cannot_pocket_x") end
if GAMEMODE.Config.PocketBlacklist[class] then return false, DarkRP.getPhrase("cannot_pocket_x") end
if string.find(class, "func_") then return false, DarkRP.getPhrase("cannot_pocket_x") end
if item:IsRagdoll() then return false, DarkRP.getPhrase("cannot_pocket_x") end
if item:IsNPC() then return false, DarkRP.getPhrase("cannot_pocket_x") end
if not duplicator.IsAllowed(class) then return false, DarkRP.getPhrase("cannot_pocket_x") end
-- Entities being held by the gravgun have different properties than
-- entities not being held. One such property is mass, which is set to 1.
-- The simple solution is to disallow pocketing entities that are being
-- held.
if item.DarkRPBeingGravGunHeldBy ~= nil then return false, DarkRP.getPhrase("cannot_pocket_gravgunned") end
local trace = ply:GetEyeTrace()
if ply:EyePos():DistToSqr(trace.HitPos) > 22500 then return false end
local ent = trace.Entity
local phys = ent:GetPhysicsObject()
if not phys:IsValid() then return false end
local mass = ent.RPOriginalMass and ent.RPOriginalMass or phys:GetMass()
if mass > 100 then return false, DarkRP.getPhrase("object_too_heavy") end
local job = ply:Team()
local max = RPExtraTeams[job].maxpocket or GAMEMODE.Config.pocketitems
if table.Count(ply.darkRPPocket or {}) >= max then return false, DarkRP.getPhrase("pocket_full") end
return true
end
-- Drop pocket items on death
hook.Add("PlayerDeath", "DropPocketItems", function(ply)
if not GAMEMODE.Config.droppocketdeath or not ply.darkRPPocket then return end
dropAllPocketItems(ply)
end)
hook.Add("playerArrested", "DropPocketItems", function(ply)
if not GAMEMODE.Config.droppocketarrest then return end
dropAllPocketItems(ply)
end)

View File

@@ -0,0 +1,169 @@
AddCSLuaFile()
if CLIENT then
SWEP.DrawAmmo = false
SWEP.DrawCrosshair = false
end
DEFINE_BASECLASS("weapon_cs_base2")
SWEP.Author = "DarkRP Developers"
SWEP.Contact = ""
SWEP.Purpose = ""
SWEP.IconLetter = ""
SWEP.ViewModelFOV = 62
SWEP.ViewModelFlip = false
SWEP.AnimPrefix = "stunstick"
SWEP.UseHands = false
SWEP.AdminOnly = true
SWEP.StickColor = color_white
SWEP.ViewModel = Model("models/weapons/v_stunbaton.mdl")
SWEP.WorldModel = Model("models/weapons/w_stunbaton.mdl")
SWEP.Sound = Sound("weapons/stunstick/stunstick_swing1.wav")
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = 0
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = ""
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = 0
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = ""
function SWEP:SetupDataTables()
BaseClass.SetupDataTables(self)
-- Bool 0 = IronsightsPredicted
-- Bool 1 = Reloading
self:NetworkVar("Bool", 2, "SeqIdling")
-- Float 0 = IronsightsTime
-- Float 1 = LastPrimaryAttack
-- Float 2 = ReloadEndTime
-- Float 3 = BurstTime
self:NetworkVar("Float", 4, "SeqIdleTime")
self:NetworkVar("Float", 5, "HoldTypeChangeTime")
end
local stunstickMaterials
function SWEP:Initialize()
self:SetHoldType("normal")
self.stickRange = 90
if SERVER then return end
stunstickMaterials = stunstickMaterials or {}
local materialName = "darkrp/" .. self:GetClass()
if stunstickMaterials[materialName] then return end
CreateMaterial(materialName, "VertexLitGeneric", {
["$basetexture"] = "models/debug/debugwhite",
["$surfaceprop"] = "metal",
["$envmap"] = "env_cubemap",
["$envmaptint"] = "[ .5 .5 .5 ]",
["$selfillum"] = 0,
["$model"] = 1
}):SetVector("$color2", self.StickColor:ToVector())
stunstickMaterials[materialName] = true
end
function SWEP:Deploy()
BaseClass.Deploy(self)
if SERVER then
self:SetMaterial("!darkrp/" .. self:GetClass())
end
local vm = self:GetOwner():GetViewModel()
if not IsValid(vm) then return true end
vm:SendViewModelMatchingSequence(vm:LookupSequence("idle01"))
return true
end
function SWEP:PreDrawViewModel(vm)
for i = 9, 15 do
vm:SetSubMaterial(i, "!darkrp/" .. self:GetClass())
end
end
function SWEP:ViewModelDrawn(vm)
if not IsValid(vm) then return end
vm:SetSubMaterial() -- clear sub-materials
end
function SWEP:ResetStick()
if not IsValid(self:GetOwner()) then return end
if SERVER then
self:SetMaterial() -- clear material
end
self:SetSeqIdling(false)
self:SetSeqIdleTime(0)
self:SetHoldTypeChangeTime(0)
end
function SWEP:Holster()
BaseClass.Holster(self)
self:ResetStick()
return true
end
function SWEP:Think()
if self:GetSeqIdling() then
self:SetSeqIdling(false)
if not IsValid(self:GetOwner()) then return end
self:GetOwner():SetAnimation(PLAYER_ATTACK1)
self:EmitSound(self.Sound)
local vm = self:GetOwner():GetViewModel()
if not IsValid(vm) then return end
vm:SendViewModelMatchingSequence(vm:LookupSequence("attackch"))
vm:SetPlaybackRate(1 + 1 / 3)
local duration = vm:SequenceDuration() / vm:GetPlaybackRate()
local time = CurTime() + duration
self:SetSeqIdleTime(time)
self:SetNextPrimaryFire(time)
end
if self:GetSeqIdleTime() ~= 0 and CurTime() >= self:GetSeqIdleTime() then
self:SetSeqIdleTime(0)
if not IsValid(self:GetOwner()) then return end
local vm = self:GetOwner():GetViewModel()
if not IsValid(vm) then return end
vm:SendViewModelMatchingSequence(vm:LookupSequence("idle01"))
end
if self:GetHoldTypeChangeTime() ~= 0 and CurTime() >= self:GetHoldTypeChangeTime() then
self:SetHoldTypeChangeTime(0)
self:SetHoldType("normal")
end
end
function SWEP:PrimaryAttack()
self:SetHoldType("melee")
self:SetHoldTypeChangeTime(CurTime() + 0.3)
self:SetNextPrimaryFire(CurTime() + 0.51) -- Actual delay is set later.
local vm = self:GetOwner():GetViewModel()
if IsValid(vm) then
vm:SendViewModelMatchingSequence(vm:LookupSequence("idle01"))
self:SetSeqIdling(true)
end
end
function SWEP:SecondaryAttack()
-- Do nothing
end
function SWEP:Reload()
-- Do nothing
end

View File

@@ -0,0 +1,196 @@
AddCSLuaFile()
if CLIENT then
SWEP.Slot = 0
SWEP.SlotPos = 5
SWEP.RenderGroup = RENDERGROUP_BOTH
killicon.AddAlias("stunstick", "weapon_stunstick")
CreateMaterial("darkrp/stunstick_beam", "UnlitGeneric", {
["$basetexture"] = "sprites/lgtning",
["$additive"] = 1
})
end
DEFINE_BASECLASS("stick_base")
SWEP.Instructions = "Left click to discipline\nRight click to kill\nHold reload to threaten"
SWEP.IsDarkRPStunstick = true
SWEP.PrintName = "Stun Stick"
SWEP.Spawnable = true
SWEP.Category = "DarkRP (Utility)"
SWEP.StickColor = Color(0, 0, 255)
function SWEP:Initialize()
BaseClass.Initialize(self)
self.Hit = {
Sound("weapons/stunstick/stunstick_impact1.wav"),
Sound("weapons/stunstick/stunstick_impact2.wav")
}
self.FleshHit = {
Sound("weapons/stunstick/stunstick_fleshhit1.wav"),
Sound("weapons/stunstick/stunstick_fleshhit2.wav")
}
end
function SWEP:SetupDataTables()
BaseClass.SetupDataTables(self)
-- Float 0 = IronsightsTime
-- Float 1 = LastPrimaryAttack
-- Float 2 = ReloadEndTime
-- Float 3 = BurstTime
-- Float 4 = SeqIdleTime
-- Float 5 = HoldTypeChangeTime
self:NetworkVar("Float", 6, "LastReload")
end
function SWEP:Think()
BaseClass.Think(self)
if self.WaitingForAttackEffect and self:GetSeqIdleTime() ~= 0 and CurTime() >= self:GetSeqIdleTime() - 0.35 then
self.WaitingForAttackEffect = false
local Owner = self:GetOwner()
local effectData = EffectData()
effectData:SetOrigin(Owner:GetShootPos() + (Owner:EyeAngles():Forward() * 45))
effectData:SetNormal(Owner:EyeAngles():Forward())
util.Effect("StunstickImpact", effectData)
end
end
function SWEP:DoFlash(ply)
if not IsValid(ply) or not ply:IsPlayer() then return end
ply:ScreenFade(SCREENFADE.IN, color_white, 1.2, 0)
end
local stunstickMaterial = Material("effects/stunstick")
local stunstickBeam = Material("!darkrp/stunstick_beam")
local colorSprite = Color(180, 180, 180)
function SWEP:PostDrawViewModel(vm)
if self:GetSeqIdleTime() ~= 0 or self:GetLastReload() >= CurTime() - 0.1 then
local attachment = vm:GetAttachment(1)
local pos = attachment.Pos
cam.Start3D(EyePos(), EyeAngles())
render.SetMaterial(stunstickMaterial)
render.DrawSprite(pos, 12, 12, colorSprite)
for i = 1, 3 do
local randVec = VectorRand() * 3
local offset = (attachment.Ang:Forward() * randVec.x) + (attachment.Ang:Right() * randVec.y) + (attachment.Ang:Up() * randVec.z)
render.SetMaterial(stunstickBeam)
render.DrawBeam(pos, pos + offset, 3.25 - i, 1, 1.25, colorSprite)
pos = pos + offset
end
cam.End3D()
end
end
local light_glow02_add = Material("sprites/light_glow02_add")
function SWEP:DrawWorldModelTranslucent()
if CurTime() <= self:GetLastReload() + 0.1 then
local bone = self:GetOwner():LookupBone("ValveBiped.Bip01_R_Hand")
if not bone then self:DrawModel() return end
local bonePos, boneAng = self:GetOwner():GetBonePosition(bone)
if bonePos then
local pos = bonePos + (boneAng:Up() * -16) + (boneAng:Right() * 3) + (boneAng:Forward() * 6.5)
render.SetMaterial(light_glow02_add)
render.DrawSprite(pos, 32, 32, color_white)
end
end
self:DrawModel()
end
local entMeta = FindMetaTable("Entity")
function SWEP:DoAttack(dmg)
if CLIENT then return end
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
Owner:LagCompensation(true)
local trace = util.QuickTrace(Owner:EyePos(), Owner:GetAimVector() * 90, {Owner})
Owner:LagCompensation(false)
local ent = trace.Entity
if IsValid(ent) and ent.onStunStickUsed then
ent:onStunStickUsed(Owner)
return
elseif IsValid(ent) and ent:GetClass() == "func_breakable_surf" then
ent:Fire("Shatter")
Owner:EmitSound(self.Hit[math.random(#self.Hit)])
return
end
self.WaitingForAttackEffect = true
ent = Owner:getEyeSightHitEntity(
self.stickRange,
15,
fn.FAnd{
fp{fn.Neq, Owner},
fc{IsValid, entMeta.GetPhysicsObject},
entMeta.IsSolid
}
)
if not IsValid(ent) then return end
if ent:IsPlayer() and not ent:Alive() then return end
if not ent:isDoor() then
ent:SetVelocity((ent:GetPos() - Owner:GetPos()) * 7)
end
if dmg > 0 then
ent:TakeDamage(dmg, Owner, self)
end
if ent:IsPlayer() or ent:IsNPC() or ent:IsVehicle() then
self:DoFlash(ent)
Owner:EmitSound(self.FleshHit[math.random(#self.FleshHit)])
else
Owner:EmitSound(self.Hit[math.random(#self.Hit)])
if FPP and FPP.plyCanTouchEnt(Owner, ent, "EntityDamage") then
if ent.SeizeReward and not ent.beenSeized and not ent.burningup and Owner:isCP() and ent.Getowning_ent and Owner ~= ent:Getowning_ent() then
local amount = isfunction(ent.SeizeReward) and ent:SeizeReward(Owner, dmg) or ent.SeizeReward
Owner:addMoney(amount)
DarkRP.notify(Owner, 1, 4, DarkRP.getPhrase("you_received_x", DarkRP.formatMoney(amount), DarkRP.getPhrase("bonus_destroying_entity")))
ent.beenSeized = true
end
local health = math.max(ent:Health(), ent:GetMaxHealth())
health = health == 0 and 1000 or health
local dmgToTake = GAMEMODE.Config.stunstickdamage <= 1 and GAMEMODE.Config.stunstickdamage * health or GAMEMODE.Config.stunstickdamage
-- Ceil because health is an integer value
dmgToTake = math.max(0, math.ceil(dmgToTake - dmg))
ent:TakeDamage(dmgToTake, Owner, self) -- for illegal entities
end
end
end
function SWEP:PrimaryAttack()
BaseClass.PrimaryAttack(self)
self:SetNextSecondaryFire(self:GetNextPrimaryFire())
self:DoAttack(0)
end
function SWEP:SecondaryAttack()
BaseClass.PrimaryAttack(self)
self:SetNextSecondaryFire(self:GetNextPrimaryFire())
self:DoAttack(10)
end
function SWEP:Reload()
self:SetHoldType("melee")
self:SetHoldTypeChangeTime(CurTime() + 0.1)
if self:GetLastReload() + 0.1 > CurTime() then self:SetLastReload(CurTime()) return end
self:SetLastReload(CurTime())
self:EmitSound("weapons/stunstick/spark" .. math.random(1, 3) .. ".wav")
end

View File

@@ -0,0 +1,107 @@
AddCSLuaFile()
if CLIENT then
SWEP.Slot = 1
SWEP.SlotPos = 3
end
DEFINE_BASECLASS("stick_base")
SWEP.Instructions = "Left click to unarrest\nRight click to switch batons"
SWEP.IsDarkRPUnarrestStick = true
SWEP.PrintName = "Unarrest Baton"
SWEP.Spawnable = true
SWEP.Category = "DarkRP (Utility)"
SWEP.StickColor = Color(0, 255, 0)
DarkRP.hookStub{
name = "canUnarrest",
description = "Whether someone can unarrest another player.",
parameters = {
{
name = "unarrester",
description = "The player trying to unarrest someone.",
type = "Player"
},
{
name = "unarrestee",
description = "The player being unarrested.",
type = "Player"
}
},
returns = {
{
name = "canUnarrest",
description = "A yes or no as to whether the player can unarrest the other player.",
type = "boolean"
},
{
name = "message",
description = "The message that is shown when they can't unarrest the player.",
type = "string"
}
},
realm = "Server"
}
-- Default for canUnarrest hook
local hookCanUnarrest = {canUnarrest = fp{fn.Id, true}}
function SWEP:Deploy()
self.Switched = true
return BaseClass.Deploy(self)
end
function SWEP:PrimaryAttack()
BaseClass.PrimaryAttack(self)
if CLIENT then return end
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
Owner:LagCompensation(true)
local trace = util.QuickTrace(Owner:EyePos(), Owner:GetAimVector() * 90, {Owner})
Owner:LagCompensation(false)
local ent = trace.Entity
if IsValid(ent) and ent.onUnArrestStickUsed then
ent:onUnArrestStickUsed(Owner)
return
end
ent = Owner:getEyeSightHitEntity(nil, nil, function(p) return p ~= Owner and p:IsPlayer() and p:Alive() and p:IsSolid() end)
if not ent then return end
local stickRange = self.stickRange * self.stickRange
if not IsValid(ent) or not ent:IsPlayer() or (Owner:EyePos():DistToSqr(ent:GetPos()) > stickRange) or not ent:getDarkRPVar("Arrested") then
return
end
local canUnarrest, message = hook.Call("canUnarrest", hookCanUnarrest, Owner, ent)
if not canUnarrest then
if message then DarkRP.notify(Owner, 1, 5, message) end
return
end
ent:unArrest(Owner)
DarkRP.notify(ent, 0, 4, DarkRP.getPhrase("youre_unarrested_by", Owner:Nick()))
if Owner.SteamName then
DarkRP.log(Owner:Nick() .. " (" .. Owner:SteamID() .. ") unarrested " .. ent:Nick(), Color(0, 255, 255))
end
end
function SWEP:startDarkRPCommand(usrcmd)
if game.SinglePlayer() and CLIENT then return end
if usrcmd:KeyDown(IN_ATTACK2) then
if not self.Switched and self:GetOwner():HasWeapon("arrest_stick") then
usrcmd:SelectWeapon(self:GetOwner():GetWeapon("arrest_stick"))
end
else
self.Switched = false
end
end

View File

@@ -0,0 +1,49 @@
AddCSLuaFile()
if CLIENT then
SWEP.Author = "DarkRP Developers"
SWEP.Slot = 3
SWEP.SlotPos = 0
SWEP.IconLetter = "b"
killicon.AddFont("weapon_ak472", "CSKillIcons", SWEP.IconLetter, Color(255, 80, 0, 255))
end
SWEP.Base = "weapon_cs_base2"
SWEP.PrintName = "AK47"
SWEP.Spawnable = true
SWEP.AdminOnly = false
SWEP.Category = "DarkRP (Weapon)"
SWEP.UseHands = true
SWEP.ViewModel = "models/weapons/cstrike/c_rif_ak47.mdl"
SWEP.WorldModel = "models/weapons/w_rif_ak47.mdl"
SWEP.Weight = 5
SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom = false
SWEP.HoldType = "ar2"
SWEP.LoweredHoldType = "passive"
SWEP.Primary.Sound = Sound("Weapon_AK47.Single")
SWEP.Primary.Recoil = 1.5
SWEP.Primary.Damage = 40
SWEP.Primary.NumShots = 1
SWEP.Primary.Cone = 0.002
SWEP.Primary.ClipSize = 30
SWEP.Primary.Delay = 0.08
SWEP.Primary.DefaultClip = 30
SWEP.Primary.Automatic = true
SWEP.Primary.Ammo = "smg1"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
SWEP.IronSightsPos = Vector(-6.6, -15, 2.6)
SWEP.IronSightsAng = Vector(2.6, 0.02, 0)
SWEP.MultiMode = true

View File

@@ -0,0 +1,19 @@
AddCSLuaFile()
DarkRP.declareChatCommand{
command = "drop",
description = "Drop the weapon you're holding.",
delay = 1.5
}
DarkRP.declareChatCommand{
command = "dropweapon",
description = "Drop the weapon you're holding.",
delay = 1.5
}
DarkRP.declareChatCommand{
command = "weapondrop",
description = "Drop the weapon you're holding.",
delay = 1.5
}

View File

@@ -0,0 +1,516 @@
AddCSLuaFile()
if SERVER then
include("sv_commands.lua")
include("sh_commands.lua")
SWEP.Weight = 5
SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom = false
end
if CLIENT then
SWEP.DrawAmmo = true
SWEP.DrawCrosshair = false
SWEP.ViewModelFOV = 82
SWEP.ViewModelFlip = false
SWEP.CSMuzzleFlashes = true
-- This is the font that's used to draw the death icons
surface.CreateFont("CSKillIcons", {
size = ScreenScale(30),
weight = 500,
antialias = true,
shadow = true,
font = "csd"
})
surface.CreateFont("CSSelectIcons", {
size = ScreenScale(60),
weight = 500,
antialias = true,
shadow = true,
font = "csd"
})
end
SWEP.Base = "weapon_base"
SWEP.Author = "DarkRP Developers"
SWEP.Contact = ""
SWEP.Purpose = ""
SWEP.Instructions = ""
SWEP.Spawnable = false
SWEP.AdminOnly = false
SWEP.UseHands = true
SWEP.HoldType = "normal"
SWEP.LoweredHoldType = "normal"
SWEP.Primary.Sound = Sound("Weapon_AK47.Single")
SWEP.Primary.Recoil = 1.5
SWEP.Primary.Damage = 40
SWEP.Primary.NumShots = 1
SWEP.Primary.Cone = 0.02
SWEP.Primary.Delay = 0.15
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = -1
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "none"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
SWEP.MultiMode = false
SWEP.DarkRPBased = true
function SWEP:SetIronsights(b)
if (b ~= self:GetIronsights()) then
self:SetIronsightsPredicted(b)
self:SetIronsightsTime(CurTime())
if GAMEMODE.Config.ironshoot then
self:SetHoldType(b and self.HoldType or self.LoweredHoldType)
end
if CLIENT then
self:CalcViewModel()
end
end
end
function SWEP:GetIronsights()
return self:GetIronsightsPredicted()
end
--- Dummy functions that will be replaced when SetupDataTables runs. These are
--- here for when that does not happen (due to e.g. stacking base classes)
function SWEP:GetIronsightsTime() return -1 end
function SWEP:SetIronsightsTime() end
function SWEP:GetIronsightsPredicted() return false end
function SWEP:SetIronsightsPredicted() end
function SWEP:SetupDataTables()
self:NetworkVar("Bool", 0, "IronsightsPredicted")
self:NetworkVar("Float", 0, "IronsightsTime")
self:NetworkVar("Bool", 1, "Reloading")
self:NetworkVar("Float", 1, "LastPrimaryAttack")
self:NetworkVar("Float", 2, "ReloadEndTime")
self:NetworkVar("Float", 3, "BurstTime")
self:NetworkVar("Int", 0, "BurstBulletNum")
self:NetworkVar("Int", 1, "TotalUsedMagCount")
self:NetworkVar("String", 0, "FireMode")
self:NetworkVar("Entity", 0, "LastOwner")
end
function SWEP:Initialize()
if CLIENT and IsValid(self:GetOwner()) then
local vm = self:GetOwner():GetViewModel()
self:ResetDarkRPBones(vm)
end
self:SetHoldType(GAMEMODE.Config.ironshoot and self.LoweredHoldType or self.HoldType)
if SERVER then
self:SetNPCMinBurst(30)
self:SetNPCMaxBurst(30)
self:SetNPCFireRate(0.01)
end
self:SetFireMode(self.Primary.Automatic and "auto" or "semi")
end
function SWEP:Deploy()
self:SetHoldType(GAMEMODE.Config.ironshoot and self.LoweredHoldType or self.HoldType)
self:SetIronsights(false)
self:SetReloading(false)
self:SetReloadEndTime(0)
self:SetBurstTime(0)
self:SetBurstBulletNum(0)
return true
end
function SWEP:Holster()
self:SetIronsights(false)
self:SetReloading(false)
self:SetReloadEndTime(0)
self:SetBurstTime(0)
self:SetBurstBulletNum(0)
if CLIENT then self.hasShot = false end
if not IsValid(self:GetOwner()) then return true end
if CLIENT then
local vm = self:GetOwner():GetViewModel()
self:ResetDarkRPBones(vm)
end
return true
end
function SWEP:OnRemove()
if CLIENT and IsValid(self:GetOwner()) then
local vm = self:GetOwner():GetViewModel()
self:ResetDarkRPBones(vm)
end
end
function SWEP:OwnerChanged()
if IsValid(self:GetOwner()) then self:SetLastOwner(self:GetOwner()) end
end
function SWEP:PrimaryAttack()
self.Primary.Automatic = self:GetFireMode() == "auto"
if self:GetBurstBulletNum() > 0 and CurTime() < self:GetBurstTime() then return end
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
if self.MultiMode and Owner:KeyDown(IN_USE) then
if self:GetFireMode() == "semi" then
self:SetFireMode("burst")
self.Primary.Automatic = false
Owner:PrintMessage(HUD_PRINTCENTER, DarkRP.getPhrase("switched_burst"))
elseif self:GetFireMode() == "burst" then
self:SetFireMode("auto")
self.Primary.Automatic = true
Owner:PrintMessage(HUD_PRINTCENTER, DarkRP.getPhrase("switched_fully_auto"))
elseif self:GetFireMode() == "auto" then
self:SetFireMode("semi")
self.Primary.Automatic = false
Owner:PrintMessage(HUD_PRINTCENTER, DarkRP.getPhrase("switched_semi_auto"))
end
self:SetNextPrimaryFire(CurTime() + 0.5)
self:SetNextSecondaryFire(CurTime() + 0.5)
return
end
if self:GetFireMode() ~= "burst" then
self:SetNextPrimaryFire(CurTime() + self.Primary.Delay)
end
self:SetNextSecondaryFire(CurTime() + self.Primary.Delay)
if self:Clip1() <= 0 then
self:EmitSound("weapons/clipempty_rifle.wav")
self:SetNextPrimaryFire(CurTime() + 2)
return
end
if not self:CanPrimaryAttack() then self:SetIronsights(false) return end
if not self:GetIronsights() and GAMEMODE.Config.ironshoot then return end
-- Play shoot sound
self:EmitSound(self.Primary.Sound)
-- Shoot the bullet
self:CSShootBullet(self.Primary.Damage, self.Primary.Recoil + 3, self.Primary.NumShots, self.Primary.Cone + .05)
if self:GetFireMode() == "burst" then
self:SetBurstBulletNum(self:GetBurstBulletNum() + 1)
if self:GetBurstBulletNum() == 3 then
self:SetBurstTime(0)
self:SetBurstBulletNum(0)
else
self:SetBurstTime(CurTime() + 0.1)
end
end
-- Remove 1 bullet from our clip
self:TakePrimaryAmmo(1)
self:SetLastPrimaryAttack(CurTime())
if Owner:IsNPC() then return end
-- Punch the player's view
Owner:ViewPunch(Angle(util.SharedRandom("DarkRP_CSBase" .. self:EntIndex() .. "Mag" .. self:GetTotalUsedMagCount() .. "p" .. self:Clip1(), -1.2, -1.1) * self.Primary.Recoil, util.SharedRandom("DarkRP_CSBase" .. self:EntIndex() .. "Mag" .. self:GetTotalUsedMagCount() .. "y" .. self:Clip1(), -1.1, 1.1) * self.Primary.Recoil, 0))
end
function SWEP:CSShootBullet(dmg, recoil, numbul, cone)
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
numbul = numbul or 1
cone = cone or 0.01
local bullet = {}
bullet.Num = numbul or 1
bullet.Src = Owner:GetShootPos() -- Source
bullet.Dir = (Owner:GetAimVector():Angle() + Owner:GetViewPunchAngles()):Forward() -- Dir of bullet
bullet.Spread = Vector(cone, cone, 0) -- Aim Cone
bullet.Tracer = 4 -- Show a tracer on every x bullets
bullet.Force = 5 -- Amount of force to give to phys objects
bullet.Damage = dmg
Owner:FireBullets(bullet)
self:SendWeaponAnim(ACT_VM_PRIMARYATTACK) -- View model animation
Owner:MuzzleFlash() -- Crappy muzzle light
Owner:SetAnimation(PLAYER_ATTACK1) -- 3rd Person Animation
if Owner:IsNPC() then return end
-- Part of workaround, different viewmodel position if shots have been fired
if CLIENT then self.hasShot = true end
end
local host_timescale = GetConVar("host_timescale")
local IRONSIGHT_TIME = 0.25
function SWEP:GetViewModelPosition(pos, ang)
if (not self.IronSightsPos) then return pos, ang end
pos = pos + ang:Forward() * -5
if (self.bIron == nil) then return pos, ang end
local bIron = self.bIron
local time = self.fCurrentTime + (SysTime() - self.fCurrentSysTime) * game.GetTimeScale() * host_timescale:GetFloat()
if bIron then
self.SwayScale = 0.3
self.BobScale = 0.1
else
self.SwayScale = 1.0
self.BobScale = 1.0
end
if GAMEMODE.Config.ironshoot then
ang:RotateAroundAxis(ang:Right(), -15)
end
local fIronTime = self.fIronTime
if (not bIron) and fIronTime < time - IRONSIGHT_TIME then
return pos, ang
end
local mul = 1.0
if fIronTime > time - IRONSIGHT_TIME then
mul = math.Clamp((time - fIronTime) / IRONSIGHT_TIME, 0, 1)
if not bIron then mul = 1 - mul end
end
local offset = self.IronSightsPos
if self.IronSightsAng then
ang = ang * 1
ang:RotateAroundAxis(ang:Right(), self.IronSightsAng.x * mul)
ang:RotateAroundAxis(ang:Up(), self.IronSightsAng.y * mul)
ang:RotateAroundAxis(ang:Forward(), self.IronSightsAng.z * mul)
end
if GAMEMODE.Config.ironshoot then
ang:RotateAroundAxis(ang:Right(), mul * 15)
else
ang:RotateAroundAxis(ang:Right(), mul)
end
pos = pos + offset.x * ang:Right() * mul
pos = pos + offset.y * ang:Forward() * mul
pos = pos + offset.z * ang:Up() * mul
if not self.hasShot then
if self.IronSightsAngAfterShootingAdjustment then
ang:RotateAroundAxis(ang:Right(), self.IronSightsAngAfterShootingAdjustment.x * mul)
ang:RotateAroundAxis(ang:Up(), self.IronSightsAngAfterShootingAdjustment.y * mul)
ang:RotateAroundAxis(ang:Forward(), self.IronSightsAngAfterShootingAdjustment.z * mul)
end
if self.IronSightsPosAfterShootingAdjustment then
offset = self.IronSightsPosAfterShootingAdjustment
local right = ang:Right()
local up = ang:Up()
local forward = ang:Forward()
pos = pos + offset.x * right * mul
pos = pos + offset.y * forward * mul
pos = pos + offset.z * up * mul
end
end
return pos, ang
end
function SWEP:SecondaryAttack()
if not self.IronSightsPos then return end
if self:GetReloading() then return end
self:SetIronsights(not self:GetIronsights())
self:SetNextSecondaryFire(CurTime() + 0.3)
end
--[[---------------------------------------------------------
Reload does nothing
---------------------------------------------------------]]
function SWEP:Reload()
if not self:DefaultReload(ACT_VM_RELOAD) then return end
self:SetReloading(true)
self:SetIronsights(false)
self:SetBurstTime(0)
self:SetBurstBulletNum(0)
self:GetOwner():SetAnimation(PLAYER_RELOAD)
self:SetReloadEndTime(CurTime() + 2)
self:SetTotalUsedMagCount(self:GetTotalUsedMagCount() + 1)
end
function SWEP:OnRestore()
self:SetNextSecondaryFire(0)
self:SetIronsights(false)
end
function SWEP:Equip(NewOwner)
if self.PrimaryClipLeft and self.SecondaryClipLeft and self.PrimaryAmmoLeft and self.SecondaryAmmoLeft then
NewOwner:SetAmmo(self.PrimaryAmmoLeft, self:GetPrimaryAmmoType())
NewOwner:SetAmmo(self.SecondaryAmmoLeft, self:GetSecondaryAmmoType())
self:SetClip1(self.PrimaryClipLeft)
self:SetClip2(self.SecondaryClipLeft)
end
end
function SWEP:OnDrop()
self.PrimaryClipLeft = self:Clip1()
self.SecondaryClipLeft = self:Clip2()
if not IsValid(self:GetLastOwner()) then return end
self.PrimaryAmmoLeft = self:GetLastOwner():GetAmmoCount(self:GetPrimaryAmmoType())
self.SecondaryAmmoLeft = self:GetLastOwner():GetAmmoCount(self:GetSecondaryAmmoType())
self:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE_DEBRIS)
end
function SWEP:CalcViewModel()
if (not CLIENT) or (not IsFirstTimePredicted()) then return end
self.bIron = self:GetIronsights()
self.fIronTime = self:GetIronsightsTime()
self.fCurrentTime = CurTime()
self.fCurrentSysTime = SysTime()
end
-- Note that if you override Think in your SWEP, you should call
-- BaseClass.Think(self) so as not to break ironsights
function SWEP:Think()
self:CalcViewModel()
if self.Primary.ClipSize ~= -1 and not self:GetReloading() and not self:GetIronsights() and self:GetLastPrimaryAttack() + 1 < CurTime() and self:GetHoldType() == self.HoldType and GAMEMODE.Config.ironshoot then
self:SetHoldType(self.LoweredHoldType)
end
if self:GetReloadEndTime() ~= 0 and CurTime() >= self:GetReloadEndTime() then
self:SetReloadEndTime(0)
self:SetReloading(false)
if GAMEMODE.Config.ironshoot then
self:SetHoldType(self.LoweredHoldType)
end
if CLIENT then self.hasShot = false end
end
if self:GetBurstTime() ~= 0 and CurTime() >= self:GetBurstTime() then
self:PrimaryAttack()
end
end
function SWEP:DrawWeaponSelection(x, y, wide, tall, alpha)
if self.IconLetter and string.find(self.IconLetter, "^[0-9a-wA-Z]$") then
draw.DrawNonParsedSimpleText(self.IconLetter, "CSSelectIcons", x + wide / 2, y + tall * 0.2, Color(255, 210, 0, 255), TEXT_ALIGN_CENTER)
-- try to fool them into thinking they're playing a Tony Hawks game
draw.DrawNonParsedSimpleText(self.IconLetter, "CSSelectIcons", x + wide / 2 + math.Rand(-4, 4), y + tall * 0.2 + math.Rand(-14, 14), Color(255, 210, 0, math.Rand(10, 120)), TEXT_ALIGN_CENTER)
draw.DrawNonParsedSimpleText(self.IconLetter, "CSSelectIcons", x + wide / 2 + math.Rand(-4, 4), y + tall * 0.2 + math.Rand(-9, 9), Color(255, 210, 0, math.Rand(10, 120)), TEXT_ALIGN_CENTER)
else
-- Set us up the texture
surface.SetDrawColor(255, 255, 255, alpha)
surface.SetTexture(self.WepSelectIcon)
-- Lets get a sin wave to make it bounce
local fsin = 0
if self.BounceWeaponIcon then
fsin = math.sin(CurTime() * 10) * 5
end
-- Borders
y = y + 10
x = x + 10
wide = wide - 20
-- Draw that motherfucker
surface.DrawTexturedRect(x + fsin, y - fsin, wide - fsin * 2, (wide / 2) + fsin)
-- Draw weapon info box
self:PrintWeaponInfo(x + wide + 20, y + tall * 0.95, alpha)
end
end
if CLIENT then
function SWEP:ViewModelDrawn(vm)
if self.DarkRPViewModelBoneManipulations and not self:GetReloading() then
self:UpdateDarkRPBones(vm, self.DarkRPViewModelBoneManipulations)
else
self:ResetDarkRPBones(vm)
end
end
function SWEP:UpdateDarkRPBones(vm, manipulations)
if not IsValid(vm) or not vm:GetBoneCount() then return end
-- Fill in missing bone names. Things fuck up when we workaround the scale bug and bones are missing.
local bones = {}
for i = 0, vm:GetBoneCount() - 1 do
local bonename = vm:GetBoneName(i)
if manipulations[bonename] then
bones[bonename] = manipulations[bonename]
else
bones[bonename] = {
scale = Vector(1,1,1),
pos = Vector(0,0,0),
angle = Angle(0,0,0)
}
end
end
for k, v in pairs(bones) do
local bone = vm:LookupBone(k)
if not bone then continue end
-- Bone scaling seems to be buggy. Workaround.
local scale = Vector(v.scale.x, v.scale.y, v.scale.z)
local ms = Vector(1,1,1)
local cur = vm:GetBoneParent(bone)
while cur >= 0 do
local pscale = bones[vm:GetBoneName(cur)].scale
ms = ms * pscale
cur = vm:GetBoneParent(cur)
end
scale = scale * ms
if vm:GetManipulateBoneScale(bone) ~= scale then
vm:ManipulateBoneScale(bone, scale)
end
if vm:GetManipulateBonePosition(bone) ~= v.pos then
vm:ManipulateBonePosition(bone, v.pos)
end
if vm:GetManipulateBoneAngles(bone) ~= v.angle then
vm:ManipulateBoneAngles(bone, v.angle)
end
end
end
function SWEP:ResetDarkRPBones(vm)
if not IsValid(vm) or not vm:GetBoneCount() then return end
for i = 0, vm:GetBoneCount() - 1 do
vm:ManipulateBoneScale(i, Vector(1, 1, 1))
vm:ManipulateBoneAngles(i, Angle(0, 0, 0))
vm:ManipulateBonePosition(i, Vector(0, 0, 0))
end
end
end
hook.Add("SetupMove", "DarkRP_WeaponSpeed", function(ply, mv)
local wep = ply:GetActiveWeapon()
if not wep:IsValid() or not wep.DarkRPBased or not wep.GetIronsights or not wep:GetIronsights() then return end
mv:SetMaxClientSpeed(mv:GetMaxClientSpeed() / 3)
end)

View File

@@ -0,0 +1,158 @@
local meta = FindMetaTable("Player")
function meta:dropDRPWeapon(weapon)
if not weapon:IsValid() or weapon:GetOwner() ~= self or weapon.IsBeingDarkRPDropped then return end
if GAMEMODE.Config.restrictdrop then
local found = false
for k,v in pairs(CustomShipments) do
if v.entity == weapon:GetClass() then
found = true
break
end
end
if not found then return end
end
-- Mark the weapon as being dropped. This, along with the check above will
-- prevent the same weapon from being dropped twice.
weapon.IsBeingDarkRPDropped = true
local primAmmo = self:GetAmmoCount(weapon:GetPrimaryAmmoType())
self:DropWeapon(weapon) -- Drop it so the model isn't the viewmodel
weapon:SetOwner(self)
local ent = ents.Create("spawned_weapon")
local model = (weapon:GetModel() == "models/weapons/v_physcannon.mdl" and "models/weapons/w_physics.mdl") or weapon:GetModel()
model = util.IsValidModel(model) and model or "models/weapons/w_rif_ak47.mdl"
ent:SetModel(model)
ent:SetSkin(weapon:GetSkin() or 0)
ent:SetWeaponClass(weapon:GetClass())
ent.nodupe = true
ent.clip1 = weapon:Clip1()
ent.clip2 = weapon:Clip2()
ent.ammoadd = primAmmo
self:RemoveAmmo(primAmmo, weapon:GetPrimaryAmmoType())
self:RemoveAmmo(self:GetAmmoCount(weapon:GetSecondaryAmmoType()), weapon:GetSecondaryAmmoType())
local trace = {}
trace.start = self:GetShootPos()
trace.endpos = trace.start + self:GetAimVector() * 50
trace.filter = {self, weapon, ent}
local tr = util.TraceLine(trace)
ent:SetPos(tr.HitPos)
ent:Spawn()
DarkRP.placeEntity(ent, tr, self)
hook.Call("onDarkRPWeaponDropped", nil, self, ent, weapon)
weapon:Remove()
end
local function DropWeapon(ply)
local curTime = CurTime()
if (ply.DelayDropWeapon or 0) >= curTime then return "" end --Fix Dupe Weapon
local ent = ply:GetActiveWeapon()
if not ent:IsValid() or ent:GetModel() == "" then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("cannot_drop_weapon"))
return ""
end
local canDrop = hook.Call("canDropWeapon", GAMEMODE, ply, ent)
if not canDrop then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("cannot_drop_weapon"))
return ""
end
ply:DoAnimationEvent(ACT_GMOD_GESTURE_ITEM_DROP)
ply.DelayDropWeapon = curTime + 1.1
timer.Simple(1, function()
if IsValid(ply) and IsValid(ent) and ply:Alive() and ent:GetModel() ~= "" and not IsValid(ply:GetObserverTarget()) then
ply:dropDRPWeapon(ent)
end
end)
return ""
end
DarkRP.defineChatCommand("drop", DropWeapon)
DarkRP.defineChatCommand("dropweapon", DropWeapon)
DarkRP.defineChatCommand("weapondrop", DropWeapon)
DarkRP.stub{
name = "dropDRPWeapon",
description = "Drop the weapon with animations.",
parameters = {
{
name = "weapon",
description = "The weapon to drop",
type = "Entity",
optional = false
}
},
returns = {
},
metatable = meta
}
DarkRP.hookStub{
name = "onDarkRPWeaponDropped",
description = "When a player drops a weapon. Use this hook (in combination with PlayerPickupDarkRPWeapon) to store extra information about a weapon. This hook cannot prevent weapon dropping. If you want to prevent weapon dropping, use canDropWeapon instead.",
parameters = {
{
name = "ply",
description = "The player who dropped the weapon.",
type = "Player"
},
{
name = "spawned_weapon",
description = "The spawned_weapon created from the weapon that is dropped.",
type = "Entity"
},
{
name = "original_weapon",
description = "The original weapon from which the spawned_weapon is made.",
type = "Weapon"
}
},
returns = {
}
}
DarkRP.hookStub{
name = "PlayerPickupDarkRPWeapon",
description = "When a player picks up a spawned_weapon.",
parameters = {
{
name = "ply",
description = "The player who dropped the weapon.",
type = "Player"
},
{
name = "spawned_weapon",
description = "The spawned_weapon created from the weapon that is dropped.",
type = "Entity"
},
{
name = "real_weapon",
description = "The actual weapon that will be used by the player.",
type = "Weapon"
}
},
returns = {
{
name = "ShouldntContinue",
description = "Whether weapon should be picked up or not.",
type = "boolean"
}
}
}

View File

@@ -0,0 +1,46 @@
AddCSLuaFile()
if CLIENT then
SWEP.Author = "DarkRP Developers"
SWEP.Slot = 1
SWEP.SlotPos = 1
SWEP.IconLetter = "f"
killicon.AddFont("weapon_deagle2", "CSKillIcons", SWEP.IconLetter, Color(255, 80, 0, 255))
end
SWEP.Base = "weapon_cs_base2"
SWEP.PrintName = "Deagle"
SWEP.Spawnable = true
SWEP.AdminOnly = false
SWEP.Category = "DarkRP (Weapon)"
SWEP.ViewModel = "models/weapons/cstrike/c_pist_deagle.mdl"
SWEP.WorldModel = "models/weapons/w_pist_deagle.mdl"
SWEP.Weight = 5
SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom = false
SWEP.HoldType = "pistol"
SWEP.LoweredHoldType = "normal"
SWEP.Primary.Sound = Sound("Weapon_Deagle.Single")
SWEP.Primary.Recoil = 5.1
SWEP.Primary.Damage = 25
SWEP.Primary.NumShots = 1
SWEP.Primary.Cone = 0.01
SWEP.Primary.ClipSize = 7
SWEP.Primary.Delay = 0.3
SWEP.Primary.DefaultClip = 7
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "pistol"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
SWEP.IronSightsPos = Vector(-6.35, -7.5, 2.02)
SWEP.IronSightsAng = Vector(0.51, 0, 0)

View File

@@ -0,0 +1,45 @@
AddCSLuaFile()
if CLIENT then
SWEP.Author = "DarkRP Developers"
SWEP.Slot = 1
SWEP.SlotPos = 1
SWEP.IconLetter = "u"
killicon.AddFont("weapon_fiveseven2", "CSKillIcons", SWEP.IconLetter, Color(255, 80, 0, 255))
end
SWEP.Base = "weapon_cs_base2"
SWEP.PrintName = "FiveSeven"
SWEP.Spawnable = true
SWEP.AdminOnly = false
SWEP.Category = "DarkRP (Weapon)"
SWEP.ViewModel = "models/weapons/cstrike/c_pist_fiveseven.mdl"
SWEP.WorldModel = "models/weapons/w_pist_fiveseven.mdl"
SWEP.Weight = 5
SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom = false
SWEP.HoldType = "pistol"
SWEP.LoweredHoldType = "normal"
SWEP.Primary.Sound = Sound("Weapon_FiveSeven.Single")
SWEP.Primary.Recoil = .5
SWEP.Primary.Damage = 10
SWEP.Primary.NumShots = 1
SWEP.Primary.Cone = 0.03
SWEP.Primary.ClipSize = 21
SWEP.Primary.Delay = 0.05
SWEP.Primary.DefaultClip = 21
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "pistol"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
SWEP.IronSightsPos = Vector(-5.92, -6.2, 3)
SWEP.IronSightsAng = Vector(-0.5, 0.07, 0)

View File

@@ -0,0 +1,48 @@
AddCSLuaFile()
if CLIENT then
SWEP.Author = "DarkRP Developers"
SWEP.Instructions = "Shoot with it"
SWEP.Slot = 1
SWEP.SlotPos = 0
SWEP.IconLetter = "c"
killicon.AddFont("weapon_glock2", "CSKillIcons", SWEP.IconLetter, Color(255, 80, 0, 255))
end
SWEP.Base = "weapon_cs_base2"
SWEP.PrintName = "Glock"
SWEP.Spawnable = true
SWEP.AdminOnly = false
SWEP.Category = "DarkRP (Weapon)"
SWEP.ViewModel = "models/weapons/cstrike/c_pist_glock18.mdl"
SWEP.WorldModel = "models/weapons/w_pist_glock18.mdl"
SWEP.HoldType = "pistol"
SWEP.LoweredHoldType = "normal"
SWEP.Weight = 5
SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom = false
SWEP.Primary.Sound = Sound("Weapon_Glock.Single")
SWEP.Primary.Recoil = 2
SWEP.Primary.Unrecoil = 6
SWEP.Primary.Damage = 10
SWEP.Primary.NumShots = 1
SWEP.Primary.Cone = 0.05
SWEP.Primary.ClipSize = 20
SWEP.Primary.Delay = 0.06
SWEP.Primary.DefaultClip = 20
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "pistol"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
--Start of Firemode configuration
SWEP.IronSightsPos = Vector(-5.77, -6.6, 2.7)
SWEP.IronSightsAng = Vector(0.9, 0, 0)

View File

@@ -0,0 +1,59 @@
include("shared.lua")
local DrawData = {}
local KeypadCheckerHalos
net.Receive("DarkRP_keypadData", function(len)
DrawData = net.ReadTable()
hook.Add("PreDrawHalos", "KeypadCheckerHalos", KeypadCheckerHalos)
end)
local lineMat = Material("cable/chain")
local textCol = Color(0, 0, 0, 120)
local haloCol = Color(0, 255, 0, 255)
function SWEP:DrawHUD()
local screenCenter = ScrH() / 2
draw.WordBox(2, 10, screenCenter, DarkRP.getPhrase("keypad_checker_shoot_keypad"), "UiBold", textCol, color_white)
draw.WordBox(2, 10, screenCenter + 20, DarkRP.getPhrase("keypad_checker_shoot_entity"), "UiBold", textCol, color_white)
draw.WordBox(2, 10, screenCenter + 40, DarkRP.getPhrase("keypad_checker_click_to_clear"), "UiBold", textCol, color_white)
local eyePos = EyePos()
local eyeAngles = EyeAngles()
local entMessages = {}
for k,v in ipairs(DrawData or {}) do
if not IsValid(v.ent) or not IsValid(v.original) then continue end
entMessages[v.ent] = (entMessages[v.ent] or 0) + 1
local obbCenter = v.ent:OBBCenter()
local pos = v.ent:LocalToWorld(obbCenter):ToScreen()
local name = v.name and ": " .. v.name:gsub("onDown", DarkRP.getPhrase("keypad_on")):gsub("onUp", DarkRP.getPhrase("keypad_off")) or ""
draw.WordBox(2, pos.x, pos.y + entMessages[v.ent] * 16, (v.delay and v.delay .. " " .. DarkRP.getPhrase("seconds") .. " " or "") .. v.type .. name, "UiBold", textCol, color_white)
cam.Start3D(eyePos, eyeAngles)
render.SetMaterial(lineMat)
render.DrawBeam(v.original:GetPos(), v.ent:GetPos(), 2, 0.01, 20, haloCol)
cam.End3D()
end
end
KeypadCheckerHalos = function()
local drawEnts = {}
local i = 1
for k,v in ipairs(DrawData) do
if not IsValid(v.ent) then continue end
drawEnts[i] = v.ent
i = i + 1
end
if table.IsEmpty(drawEnts) then return end
halo.Add(drawEnts, haloCol, 5, 5, 5, nil, true)
end
function SWEP:SecondaryAttack()
DrawData = {}
hook.Remove("PreDrawHalos", "KeypadCheckerHalos")
end

View File

@@ -0,0 +1,187 @@
AddCSLuaFile()
if SERVER then
AddCSLuaFile("cl_init.lua")
util.AddNetworkString("DarkRP_keypadData")
end
SWEP.Base = "weapon_base"
SWEP.PrintName = "Admin Keypad Checker"
SWEP.Author = "DarkRP Developers"
SWEP.Instructions = "Left click on a keypad or fading door to check it\nRight click to clear"
SWEP.Slot = 5
SWEP.SlotPos = 1
SWEP.DrawAmmo = false
SWEP.ViewModelFlip = false
SWEP.Primary.ClipSize = 0
SWEP.Primary.Ammo = ""
SWEP.Secondary.Ammo = ""
SWEP.Spawnable = true
SWEP.AdminOnly = true
SWEP.Category = "DarkRP (Utility)"
SWEP.HoldType = "normal"
SWEP.ViewModel = Model("models/weapons/c_pistol.mdl")
SWEP.WorldModel = "models/weapons/w_toolgun.mdl"
SWEP.IconLetter = ""
SWEP.ViewModel = "models/weapons/c_pistol.mdl"
SWEP.UseHands = true
local table_insert = table.insert
local tonumber = tonumber
--[[
Gets which entities are controlled by which keyboard keys
]]
local function getTargets(keypad, keyPass, keyDenied, delayPass, delayDenied)
local targets = {}
local Owner = keypad:CPPIGetOwner()
for _, v in ipairs(numpad.OnDownItems or {}) do
if v.key == keyPass and v.ply == Owner then
table_insert(targets, {type = DarkRP.getPhrase("keypad_checker_entering_right_pass"), name = v.name, ent = v.ent, original = keypad})
end
if v.key == keyDenied and v.ply == Owner then
table_insert(targets, {type = DarkRP.getPhrase("keypad_checker_entering_wrong_pass"), name = v.name, ent = v.ent, original = keypad})
end
end
for _, v in ipairs(numpad.OnUpItems or {}) do
if v.key == keyPass and v.ply == Owner then
table_insert(targets, {type = DarkRP.getPhrase("keypad_checker_after_right_pass"), name = v.name, delay = math.Round(delayPass, 2), ent = v.ent, original = keypad})
end
if v.key == keyDenied and v.ply == Owner then
table_insert(targets, {type = DarkRP.getPhrase("keypad_checker_after_wrong_pass"), name = v.name, delay = math.Round(delayDenied, 2), ent = v.ent, original = keypad})
end
end
return targets
end
--[[---------------------------------------------------------------------------
Get the entities that are affected by the keypad
---------------------------------------------------------------------------]]
local function get_sent_keypad_Info(keypad)
local keyPass = keypad:GetNWInt("keypad_keygroup1")
local keyDenied = keypad:GetNWInt("keypad_keygroup2")
local delayPass = keypad:GetNWInt("keypad_length1")
local delayDenied = keypad:GetNWInt("keypad_length2")
return getTargets(keypad, keyPass, keyDenied, delayPass, delayDenied)
end
--[[---------------------------------------------------------------------------
Overload for a different keypad addon
---------------------------------------------------------------------------]]
local function get_keypad_Info(keypad)
local keyPass = tonumber(keypad.KeypadData.KeyGranted) or 0
local keyDenied = tonumber(keypad.KeypadData.KeyDenied) or 0
local delayPass = tonumber(keypad.KeypadData.LengthGranted) or 0
local delayDenied = tonumber(keypad.KeypadData.LengthDenied) or 0
return getTargets(keypad, keyPass, keyDenied, delayPass, delayDenied)
end
--[[---------------------------------------------------------------------------
Get the keypads that trigger this entity
---------------------------------------------------------------------------]]
local function getEntityKeypad(ent)
local targets = {}
local doorKeys = {} -- The numpad keys that activate this entity
local entOwner = ent:CPPIGetOwner()
for _, v in ipairs(numpad.OnDownItems or {}) do
if v.ent == ent then
table_insert(doorKeys, v.key)
end
end
for _, v in ipairs(numpad.OnUpItems or {}) do
if v.ent == ent then
table_insert(doorKeys, v.key)
end
end
for _, v in ipairs(ents.FindByClass("sent_keypad")) do
local vOwner = v:CPPIGetOwner()
if vOwner == entOwner and table.HasValue(doorKeys, v:GetNWInt("keypad_keygroup1")) then
table_insert(targets, {type = DarkRP.getPhrase("keypad_checker_right_pass_entered"), ent = v, original = ent})
end
if vOwner == entOwner and table.HasValue(doorKeys, v:GetNWInt("keypad_keygroup2")) then
table_insert(targets, {type = DarkRP.getPhrase("keypad_checker_wrong_pass_entered"), ent = v, original = ent})
end
end
for _, v in ipairs(ents.FindByClass("keypad")) do
local vOwner = v:CPPIGetOwner()
if vOwner == entOwner and table.HasValue(doorKeys, tonumber(v.KeypadData.KeyGranted) or 0) then
table_insert(targets, {type = DarkRP.getPhrase("keypad_checker_right_pass_entered"), ent = v, original = ent})
end
if vOwner == entOwner and table.HasValue(doorKeys, tonumber(v.KeypadData.KeyDenied) or 0) then
table_insert(targets, {type = DarkRP.getPhrase("keypad_checker_wrong_pass_entered"), ent = v, original = ent})
end
end
return targets
end
--[[---------------------------------------------------------------------------
Send the info to the client
---------------------------------------------------------------------------]]
function SWEP:PrimaryAttack()
self:SetNextPrimaryFire(CurTime() + 0.3)
if not SERVER then return end
local Owner = self:GetOwner()
local trace = Owner:GetEyeTrace()
if not IsValid(trace.Entity) then return end
local ent, class = trace.Entity, string.lower(trace.Entity:GetClass() or "")
local data
if class == "sent_keypad" then
data = get_sent_keypad_Info(ent)
DarkRP.notify(Owner, 1, 4, DarkRP.getPhrase("keypad_checker_controls_x_entities", #data / 2))
elseif class == "keypad" then
data = get_keypad_Info(ent)
DarkRP.notify(Owner, 1, 4, DarkRP.getPhrase("keypad_checker_controls_x_entities", #data / 2))
else
data = getEntityKeypad(ent)
DarkRP.notify(Owner, 1, 4, DarkRP.getPhrase("keypad_checker_controlled_by_x_keypads", #data))
end
net.Start("DarkRP_keypadData")
net.WriteTable(data)
net.Send(Owner)
end
function SWEP:SecondaryAttack()
end
if not SERVER then return end
--[[---------------------------------------------------------------------------
Registering numpad data
---------------------------------------------------------------------------]]
local oldNumpadUp = numpad.OnUp
local oldNumpadDown = numpad.OnDown
function numpad.OnUp(ply, key, name, ent, ...)
numpad.OnUpItems = numpad.OnUpItems or {}
table_insert(numpad.OnUpItems, {ply = ply, key = key, name = name, ent = ent, arg = {...}})
return oldNumpadUp(ply, key, name, ent, ...)
end
function numpad.OnDown(ply, key, name, ent, ...)
numpad.OnDownItems = numpad.OnDownItems or {}
table_insert(numpad.OnDownItems, {ply = ply, key = key, name = name, ent = ent, arg = {...}})
return oldNumpadDown(ply, key, name, ent, ...)
end

View File

@@ -0,0 +1,131 @@
AddCSLuaFile()
if CLIENT then
SWEP.Author = "DarkRP Developers"
SWEP.Contact = ""
SWEP.Purpose = ""
SWEP.Instructions = "Hold use and left-click to change firemodes."
SWEP.Slot = 2
SWEP.SlotPos = 0
SWEP.IconLetter = "w"
killicon.AddFont("weapon_m42", "CSKillIcons", SWEP.IconLetter, Color(255, 80, 0, 255))
end
SWEP.Base = "weapon_cs_base2"
SWEP.PrintName = "M4"
SWEP.Spawnable = true
SWEP.AdminOnly = false
SWEP.Category = "DarkRP (Weapon)"
SWEP.ViewModel = "models/weapons/cstrike/c_rif_m4a1.mdl"
SWEP.WorldModel = "models/weapons/w_rif_m4a1.mdl"
SWEP.HoldType = "ar2"
SWEP.LoweredHoldType = "passive"
SWEP.DarkRPViewModelBoneManipulations = {
["ValveBiped.Bip01_Spine4"] = {
scale = Vector(1, 1, 1),
pos = Vector(2, 0, 0),
angle = Angle(0, 0, 0)
},
["ValveBiped.Bip01_L_Hand"] = {
scale = Vector(0.7, 0.7, 0.5),
pos = Vector(-0.6, -0.6, 0),
angle = Angle(17, -21, 0)
},
["ValveBiped.Bip01_L_Finger0"] = {
scale = Vector(1, 1, 1.5),
pos = Vector(0, 0, 0),
angle = Angle(0, -2, 0)
},
["ValveBiped.Bip01_L_Finger1"] = {
scale = Vector(1, 1, 1.5),
pos = Vector(-0.3, -0.8, 0),
angle = Angle(0, -10, 0)
},
["ValveBiped.Bip01_L_Finger11"] = {
scale = Vector(1, 1, 1),
pos = Vector(0, 0, 0),
angle = Angle(0, -15, 0)
},
["ValveBiped.Bip01_L_Finger12"] = {
scale = Vector(1, 1, 1),
pos = Vector(0, 0, 0),
angle = Angle(0, -14, 0)
},
["ValveBiped.Bip01_L_Finger2"] = {
scale = Vector(1, 1, 1.5),
pos = Vector(-0.6, -1, -0),
angle = Angle(0, 7, 0)
},
["ValveBiped.Bip01_L_Finger21"] = {
scale = Vector(1, 1, 1),
pos = Vector(0, 0, 0),
angle = Angle(0, -15, 0)
},
["ValveBiped.Bip01_L_Finger22"] = {
scale = Vector(0.8, 0.8, 1),
pos = Vector(0, -0.3, 0),
angle = Angle(0, -36, 0)
},
["ValveBiped.Bip01_L_Finger3"] = {
scale = Vector(1, 1, 1.5),
pos = Vector(-0.36, -1.2, -0.2),
angle = Angle(-6, -2, 0)
},
["ValveBiped.Bip01_L_Finger31"] = {
scale = Vector(1, 1, 1),
pos = Vector(0, -0.1, 0),
angle = Angle(0, -4, 0)
},
["ValveBiped.Bip01_L_Finger32"] = {
scale = Vector(1, 1, 1),
pos = Vector(0, -0.2, 0),
angle = Angle(0, -12, 0)
},
["ValveBiped.Bip01_L_Finger4"] = {
scale = Vector(1, 1, 1.5),
pos = Vector(-0.3, -1.2, 0.3),
angle = Angle(12, -6.2, -4)
},
["ValveBiped.Bip01_L_Finger41"] = {
scale = Vector(1, 1, 1),
pos = Vector(0, 0, 0),
angle = Angle(0, 38, 0)
},
["ValveBiped.Bip01_L_Finger42"] = {
scale = Vector(1, 1, 1),
pos = Vector(0, 0, 0),
angle = Angle(0, 30, 0)
}
}
SWEP.Weight = 5
SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom = false
SWEP.Primary.Sound = Sound("Weapon_M4A1.Single")
SWEP.Primary.Recoil = 1.25
SWEP.Primary.Unrecoil = 8
SWEP.Primary.Damage = 15
SWEP.Primary.NumShots = 1
SWEP.Primary.Cone = 0.03
SWEP.Primary.ClipSize = 30
SWEP.Primary.Delay = 0.07
SWEP.Primary.DefaultClip = 30
SWEP.Primary.Automatic = true
SWEP.Primary.Ammo = "smg1"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
-- Start of Firemode configuration
SWEP.IronSightsPos = Vector(-8.09, -4.5, 0.56)
SWEP.IronSightsAng = Vector(2.75, -3.97, -3.8)
SWEP.IronSightsPosAfterShootingAdjustment = Vector(0.5, 0, 0)
SWEP.IronSightsAngAfterShootingAdjustment = Vector(0, 1.65, 0)
SWEP.MultiMode = true

View File

@@ -0,0 +1,46 @@
AddCSLuaFile()
if CLIENT then
SWEP.Author = "DarkRP Developers"
SWEP.Slot = 2
SWEP.SlotPos = 0
SWEP.IconLetter = "l"
killicon.AddFont("weapon_mac102", "CSKillIcons", SWEP.IconLetter, Color(255, 80, 0, 255))
end
SWEP.Base = "weapon_cs_base2"
SWEP.PrintName = "Mac10"
SWEP.Spawnable = true
SWEP.AdminOnly = false
SWEP.Category = "DarkRP (Weapon)"
SWEP.ViewModel = "models/weapons/cstrike/c_smg_mac10.mdl"
SWEP.WorldModel = "models/weapons/w_smg_mac10.mdl"
SWEP.Weight = 5
SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom = false
SWEP.HoldType = "pistol"
SWEP.LoweredHoldType = "normal"
SWEP.Primary.Sound = Sound("Weapon_mac10.Single")
SWEP.Primary.Recoil = .8
SWEP.Primary.Damage = 30
SWEP.Primary.NumShots = 1
SWEP.Primary.Cone = 0.02
SWEP.Primary.ClipSize = 25
SWEP.Primary.Delay = 0.09
SWEP.Primary.DefaultClip = 25
SWEP.Primary.Automatic = true
SWEP.Primary.Ammo = "smg1"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
SWEP.IronSightsPos = Vector(-9.08, -8, 2.6)
SWEP.IronSightsAng = Vector(1.8, -7.06, -6.1)

View File

@@ -0,0 +1,46 @@
AddCSLuaFile()
if CLIENT then
SWEP.Author = "DarkRP Developers"
SWEP.Slot = 2
SWEP.SlotPos = 0
SWEP.IconLetter = "x"
killicon.AddFont("weapon_mp52", "CSKillIcons", SWEP.IconLetter, Color(255, 80, 0, 255))
end
SWEP.Base = "weapon_cs_base2"
SWEP.PrintName = "MP5"
SWEP.Spawnable = true
SWEP.AdminOnly = false
SWEP.Category = "DarkRP (Weapon)"
SWEP.ViewModel = "models/weapons/cstrike/c_smg_mp5.mdl"
SWEP.WorldModel = "models/weapons/w_smg_mp5.mdl"
SWEP.Weight = 5
SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom = false
SWEP.HoldType = "smg"
SWEP.LoweredHoldType = "passive"
SWEP.Primary.Sound = Sound("Weapon_MP5Navy.Single")
SWEP.Primary.Recoil = 0.5
SWEP.Primary.Damage = 15
SWEP.Primary.NumShots = 1
SWEP.Primary.Cone = 0.005
SWEP.Primary.ClipSize = 32
SWEP.Primary.Delay = 0.08
SWEP.Primary.DefaultClip = 32
SWEP.Primary.Automatic = true
SWEP.Primary.Ammo = "smg1"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
SWEP.IronSightsPos = Vector(-5.3, -7, 2.1)
SWEP.IronSightsAng = Vector(0.9, 0.1, 0)

View File

@@ -0,0 +1,46 @@
AddCSLuaFile()
if CLIENT then
SWEP.Author = "DarkRP Developers"
SWEP.Slot = 1
SWEP.SlotPos = 1
SWEP.IconLetter = "y"
killicon.AddFont("weapon_p2282", "CSKillIcons", SWEP.IconLetter, Color(255, 80, 0, 255))
end
SWEP.Base = "weapon_cs_base2"
SWEP.PrintName = "P228"
SWEP.Spawnable = true
SWEP.AdminOnly = false
SWEP.Category = "DarkRP (Weapon)"
SWEP.HoldType = "pistol"
SWEP.LoweredHoldType = "normal"
SWEP.ViewModel = "models/weapons/cstrike/c_pist_p228.mdl"
SWEP.WorldModel = "models/weapons/w_pist_p228.mdl"
SWEP.Weight = 5
SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom = false
SWEP.Primary.Sound = Sound("Weapon_p228.Single")
SWEP.Primary.Recoil = 0.8
SWEP.Primary.Damage = 10
SWEP.Primary.NumShots = 1
SWEP.Primary.Cone = 0.04
SWEP.Primary.ClipSize = 12
SWEP.Primary.Delay = 0.1
SWEP.Primary.DefaultClip = 12
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "pistol"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
SWEP.IronSightsPos = Vector(-5.985, -6.7, 2.87)
SWEP.IronSightsAng = Vector(-0.3, -0.03, 0)

View File

@@ -0,0 +1,136 @@
AddCSLuaFile()
if CLIENT then
SWEP.Author = "DarkRP Developers"
SWEP.Slot = 2
SWEP.SlotPos = 0
SWEP.IconLetter = "k"
killicon.AddFont("weapon_pumpshotgun2", "CSKillIcons", SWEP.IconLetter, Color(255, 80, 0, 255))
end
DEFINE_BASECLASS("weapon_cs_base2")
SWEP.PrintName = "Pump Shotgun"
SWEP.Spawnable = true
SWEP.AdminOnly = false
SWEP.Category = "DarkRP (Weapon)"
SWEP.ViewModel = "models/weapons/cstrike/c_shot_m3super90.mdl"
SWEP.WorldModel = "models/weapons/w_shot_m3super90.mdl"
SWEP.Weight = 5
SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom = false
SWEP.HoldType = "shotgun"
SWEP.LoweredHoldType = "normal"
SWEP.Primary.Sound = Sound("Weapon_M3.Single")
SWEP.Primary.Recoil = 1.5
SWEP.Primary.Damage = 20
SWEP.Primary.NumShots = 8
SWEP.Primary.Cone = 0.08
SWEP.Primary.ClipSize = 8
SWEP.Primary.Delay = 0.95
SWEP.Primary.DefaultClip = 8
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "buckshot"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
SWEP.IronSightsPos = Vector(-7.64, -8, 3.56)
SWEP.IronSightsAng = Vector(-0.1, 0.02, 0)
function SWEP:SetupDataTables()
BaseClass.SetupDataTables(self)
-- Float 0 = IronsightsTime
-- Float 1 = LastPrimaryAttack
-- Float 2 = ReloadEndTime
-- Float 3 = BurstTime
self:NetworkVar("Float", 4, "QueuedAttackTime")
-- Bool 0 = IronsightsPredicted
-- Bool 1 = Reloading
self:NetworkVar("Bool", 2, "AttackQueued")
end
function SWEP:Deploy()
self:SetAttackQueued(false)
return BaseClass.Deploy(self)
end
function SWEP:Holster()
self:SetAttackQueued(false)
return BaseClass.Holster(self)
end
function SWEP:PrimaryAttack()
if self:GetAttackQueued() then return end
if self:GetReloading() then
self:SetAttackQueued(true) -- this way it doesn't interupt the reload animation
return
end
BaseClass.PrimaryAttack(self)
end
function SWEP:Reload()
-- Already reloading
if self:GetReloading() then return end
-- Start reloading if we can
if self:Clip1() < self.Primary.ClipSize and self:GetOwner():GetAmmoCount(self.Primary.Ammo) > 0 then
self:SetReloading(true)
self:SetReloadEndTime(CurTime() + 0.3)
self:SendWeaponAnim(ACT_VM_RELOAD)
self:SetIronsights(false)
self:SetHoldType(self.HoldType)
self:GetOwner():SetAnimation(PLAYER_RELOAD)
self:SetHoldType("normal")
end
end
function SWEP:Think()
self:CalcViewModel()
if self:GetReloadEndTime() ~= 0 and CurTime() >= self:GetReloadEndTime() then
-- Finished reload -
if self:Clip1() >= self.Primary.ClipSize or self:GetOwner():GetAmmoCount(self.Primary.Ammo) <= 0 then
self:SetReloading(false)
self:SetReloadEndTime(0)
self:SetAttackQueued(false)
return
end
if self:GetAttackQueued() then
self:SendWeaponAnim(ACT_SHOTGUN_RELOAD_FINISH)
self:SetReloading(false)
self:SetReloadEndTime(0)
self:SetAttackQueued(false)
self:SetQueuedAttackTime(CurTime() + 0.8)
return
end
-- Next cycle
self:SetReloadEndTime(CurTime() + 0.3)
self:SendWeaponAnim(ACT_VM_RELOAD)
-- Add ammo
self:GetOwner():RemoveAmmo(1, self.Primary.Ammo, false)
self:SetClip1(self:Clip1() + 1)
-- Finish filling, final pump
if self:Clip1() >= self.Primary.ClipSize or self:GetOwner():GetAmmoCount(self.Primary.Ammo) <= 0 then
self:SendWeaponAnim(ACT_SHOTGUN_RELOAD_FINISH)
end
end
if self:GetQueuedAttackTime() ~= 0 and CurTime() >= self:GetQueuedAttackTime() then
self:SetQueuedAttackTime(0)
self:PrimaryAttack()
end
end

View File

@@ -0,0 +1,409 @@
AddCSLuaFile()
if CLIENT then
SWEP.Slot = 1
SWEP.SlotPos = 9
SWEP.DrawAmmo = false
SWEP.DrawCrosshair = false
end
SWEP.Author = "DarkRP Developers"
SWEP.Instructions = "Left click to weapon check\nRight click to confiscate weapons\nReload to give back the weapons"
SWEP.Contact = ""
SWEP.Purpose = ""
SWEP.IsDarkRPWeaponChecker = true
SWEP.ViewModelFOV = 62
SWEP.ViewModelFlip = false
SWEP.AnimPrefix = "rpg"
SWEP.PrintName = "Weapon Checker"
SWEP.Spawnable = true
SWEP.AdminOnly = true
SWEP.Category = "DarkRP (Utility)"
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = 0
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = ""
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = 0
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = ""
SWEP.MinCheckTime = 5
SWEP.MaxCheckTime = 10
DarkRP.hookStub{
name = "playerWeaponsChecked",
description = "Called when a player with a weapon checker has checked another player's weapons. Note: Only called when the player looks at the weapons without confiscating. Please see playerWeaponsConfiscated for when weapons are actually confiscated.",
parameters = {
{
name = "checker",
description = "The player holding the weapon checker.",
type = "Player"
},
{
name = "target",
description = "The player whose weapons have been checked.",
type = "Player"
},
{
name = "weapons",
description = "The weapons that have been checked.",
type = "table"
},
},
returns = {},
realm = "Shared"
}
DarkRP.hookStub{
name = "playerWeaponsReturned",
description = "Called when a player with a weapon checker has returned another player's weapons.",
parameters = {
{
name = "checker",
description = "The player holding the weapon checker.",
type = "Player"
},
{
name = "target",
description = "The player whose weapons have been returned.",
type = "Player"
},
{
name = "weapons",
description = "The weapons that have been returned.",
type = "table"
},
},
returns = {},
realm = "Server"
}
DarkRP.hookStub{
name = "playerWeaponsConfiscated",
description = "Called when a player with a weapon checker has confiscated another player's weapons.",
parameters = {
{
name = "checker",
description = "The player holding the weapon checker.",
type = "Player"
},
{
name = "target",
description = "The player whose weapons have been confiscated.",
type = "Player"
},
{
name = "weapons",
description = "The weapons that have been confiscated.",
type = "table"
},
},
returns = {},
realm = "Server"
}
function SWEP:SetupDataTables()
self:NetworkVar("Bool", 0, "IsWeaponChecking")
self:NetworkVar("Float", 0, "StartCheckTime")
self:NetworkVar("Float", 1, "EndCheckTime")
self:NetworkVar("Float", 2, "NextSoundTime")
self:NetworkVar("Int", 0, "TotalWeaponChecks")
end
function SWEP:Initialize()
self:SetHoldType("normal")
end
function SWEP:Deploy()
return true
end
function SWEP:DrawWorldModel()
end
function SWEP:PreDrawViewModel(vm)
return true
end
function SWEP:GetStrippableWeapons(ent, callback)
CAMI.PlayerHasAccess(ent, "DarkRP_GetAdminWeapons", function(access)
for _, v in ipairs(ent:GetWeapons()) do
local class = v:GetClass()
if GAMEMODE.Config.weaponCheckerHideDefault and (table.HasValue(GAMEMODE.Config.DefaultWeapons, class) or
access and table.HasValue(GAMEMODE.Config.AdminWeapons, class) or
ent:getJobTable() and ent:getJobTable().weapons and table.HasValue(ent:getJobTable().weapons, class)) then
continue
end
if (GAMEMODE.Config.weaponCheckerHideNoLicense and GAMEMODE.NoLicense[class]) or GAMEMODE.Config.noStripWeapons[class] then continue end
callback(v)
end
end)
end
function SWEP:PrimaryAttack()
if self:GetIsWeaponChecking() then return end
self:SetNextPrimaryFire(CurTime() + 0.3)
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
Owner:LagCompensation(true)
local trace = Owner:GetEyeTrace()
Owner:LagCompensation(false)
local ent = trace.Entity
if not IsValid(ent) or not ent:IsPlayer() or ent:GetPos():DistToSqr(Owner:GetPos()) > 10000 then
return
end
self:EmitSound("npc/combine_soldier/gear5.wav", 50, 100)
self:SetNextSoundTime(CurTime() + 0.3)
if not IsFirstTimePredicted() then return end
local weps = {}
self:GetStrippableWeapons(ent, function(wep)
table.insert(weps, wep)
end)
hook.Call("playerWeaponsChecked", nil, Owner, ent, weps)
if not CLIENT then return end
self:PrintWeapons(ent, DarkRP.getPhrase("persons_weapons", ent:Nick()))
end
function SWEP:SecondaryAttack()
if self:GetIsWeaponChecking() then return end
self:SetNextSecondaryFire(CurTime() + 0.3)
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
Owner:LagCompensation(true)
local trace = Owner:GetEyeTrace()
Owner:LagCompensation(false)
local ent = trace.Entity
if not IsValid(ent) or not ent:IsPlayer() or ent:GetPos():DistToSqr(Owner:GetPos()) > 10000 then
return
end
self:SetIsWeaponChecking(true)
self:SetStartCheckTime(CurTime())
self:SetEndCheckTime(CurTime() + util.SharedRandom("DarkRP_WeaponChecker" .. self:EntIndex() .. "_" .. self:GetTotalWeaponChecks(), self.MinCheckTime, self.MaxCheckTime))
self:SetTotalWeaponChecks(self:GetTotalWeaponChecks() + 1)
self:SetNextSoundTime(CurTime() + 0.5)
if CLIENT then
self.Dots = ""
self.NextDotsTime = CurTime() + 0.5
end
end
function SWEP:Reload()
if CLIENT or CurTime() < (self.NextReloadTime or 0) then return end
self.NextReloadTime = CurTime() + 1
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
local trace = Owner:GetEyeTrace()
local ent = trace.Entity
if not IsValid(ent) or not ent:IsPlayer() or ent:GetPos():DistToSqr(Owner:GetPos()) > 10000 then
return
end
if not ent.ConfiscatedWeapons then
DarkRP.notify(Owner, 1, 4, DarkRP.getPhrase("no_weapons_confiscated", ent:Nick()))
return
else
ent:RemoveAllAmmo()
for _, v in pairs(ent.ConfiscatedWeapons) do
local wep = ent:Give(v.class, true)
-- :Give returns NULL when the player already has the weapon
wep = IsValid(wep) and wep or ent:GetWeapon(v.class)
if not IsValid(wep) then continue end
ent:GiveAmmo(v.primaryAmmoCount, v.primaryAmmoType, true)
ent:GiveAmmo(v.secondaryAmmoCount, v.secondaryAmmoType, true)
wep:SetClip1(v.clip1)
wep:SetClip2(v.clip2)
end
DarkRP.notify(Owner, 2, 4, DarkRP.getPhrase("returned_persons_weapons", ent:Nick()))
hook.Call("playerWeaponsReturned", nil, Owner, ent, ent.ConfiscatedWeapons)
ent.ConfiscatedWeapons = nil
end
end
function SWEP:Holster()
self:SetIsWeaponChecking(false)
self:SetNextSoundTime(0)
return true
end
function SWEP:Succeed()
if not IsValid(self:GetOwner()) then return end
self:SetIsWeaponChecking(false)
local trace = self:GetOwner():GetEyeTrace()
local ent = trace.Entity
if not IsValid(ent) or not ent:IsPlayer() then return end
if CLIENT then
if not IsFirstTimePredicted() then return end
self:PrintWeapons(ent, DarkRP.getPhrase("confiscated_these_weapons"))
return
end
local stripped = {}
self:GetStrippableWeapons(ent, function(wep)
local class = wep:GetClass()
ent:StripWeapon(class)
stripped[class] = {
class = class,
primaryAmmoCount = ent:GetAmmoCount(wep:GetPrimaryAmmoType()),
primaryAmmoType = wep:GetPrimaryAmmoType(),
secondaryAmmoCount = ent:GetAmmoCount(wep:GetSecondaryAmmoType()),
secondaryAmmoType = wep:GetSecondaryAmmoType(),
clip1 = wep:Clip1(),
clip2 = wep:Clip2()
}
end)
if not ent.ConfiscatedWeapons then
if next(stripped) ~= nil then ent.ConfiscatedWeapons = stripped end
else
-- Merge stripped weapons into confiscated weapons
for k,v in pairs(stripped) do
if ent.ConfiscatedWeapons[k] then continue end
ent.ConfiscatedWeapons[k] = v
end
end
hook.Call("playerWeaponsConfiscated", nil, self:GetOwner(), ent, ent.ConfiscatedWeapons)
if next(stripped) ~= nil then
self:EmitSound("npc/combine_soldier/gear5.wav", 50, 100)
self:SetNextSoundTime(CurTime() + 0.3)
else
self:EmitSound("ambient/energy/zap1.wav", 50, 100)
self:SetNextSoundTime(0)
end
end
function SWEP:PrintWeapons(ent, weaponsFoundPhrase)
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
local result = {}
local weps = {}
self:GetStrippableWeapons(ent, function(wep)
table.insert(weps, wep)
end)
for _, wep in ipairs(weps) do
table.insert(result, wep:GetPrintName() and language.GetPhrase(wep:GetPrintName()) or wep:GetClass())
end
result = table.concat(result, ", ")
if result == "" then
Owner:ChatPrint(DarkRP.getPhrase("no_illegal_weapons", ent:Nick()))
return
end
Owner:ChatPrint(weaponsFoundPhrase)
if string.len(result) >= 126 then
local amount = math.ceil(string.len(result) / 126)
for i = 1, amount, 1 do
Owner:ChatPrint(string.sub(result, (i-1) * 126, i * 126 - 1))
end
else
Owner:ChatPrint(result)
end
end
function SWEP:Fail()
self:SetIsWeaponChecking(false)
self:SetHoldType("normal")
self:SetNextSoundTime(0)
end
function SWEP:Think()
local Owner = self:GetOwner()
if not IsValid(Owner) then return end
if self:GetIsWeaponChecking() and self:GetEndCheckTime() ~= 0 then
Owner:LagCompensation(true)
local trace = Owner:GetEyeTrace()
Owner:LagCompensation(false)
if not IsValid(trace.Entity) or trace.HitPos:DistToSqr(Owner:GetShootPos()) > 10000 or not trace.Entity:IsPlayer() then
self:Fail()
end
if self:GetEndCheckTime() <= CurTime() then
self:Succeed()
end
end
if self:GetNextSoundTime() ~= 0 and CurTime() >= self:GetNextSoundTime() then
if self:GetIsWeaponChecking() then
self:SetNextSoundTime(CurTime() + 0.5)
self:EmitSound("npc/combine_soldier/gear5.wav", 100, 100)
else
self:SetNextSoundTime(0)
self:EmitSound("npc/combine_soldier/gear5.wav", 50, 100)
end
end
if CLIENT and self.NextDotsTime and CurTime() >= self.NextDotsTime then
self.NextDotsTime = CurTime() + 0.5
self.Dots = self.Dots or ""
local len = string.len(self.Dots)
local dots = {
[0] = ".",
[1] = "..",
[2] = "...",
[3] = ""
}
self.Dots = dots[len]
end
end
local colorBackground = Color(10, 10, 10, 120)
function SWEP:DrawHUD()
if self:GetIsWeaponChecking() and self:GetEndCheckTime() ~= 0 then
self.Dots = self.Dots or ""
local w = ScrW()
local h = ScrH()
local x, y, width, height = w / 2 - w / 10, h / 2, w / 5, h / 15
local time = self:GetEndCheckTime() - self:GetStartCheckTime()
local curtime = CurTime() - self:GetStartCheckTime()
local status = math.Clamp(curtime / time, 0, 1)
local BarWidth = status * (width - 16)
local cornerRadius = math.Min(8, BarWidth / 3 * 2 - BarWidth / 3 * 2 % 2)
draw.RoundedBox(8, x, y, width, height, colorBackground)
draw.RoundedBox(cornerRadius, x + 8, y + 8, BarWidth, height - 16, Color(0, 0 + (status * 255), 255 - (status * 255), 255))
draw.DrawNonParsedSimpleText(DarkRP.getPhrase("checking_weapons") .. self.Dots, "Trebuchet24", w / 2, y + height / 2, color_white, 1, 1)
end
end