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,60 @@
include("shared.lua")
ENT.DrawPos = Vector(1, -111, 58)
ENT.Width = 558
ENT.Height = 290
ENT.HeaderMargin = 10
ENT.BodyMargin = 10
ENT.HeaderFont = "Trebuchet48"
ENT.BodyFont = "DermaLarge"
function ENT:Draw()
self:DrawModel()
local DrawPos = self:LocalToWorld(self.DrawPos)
local DrawAngles = self:GetAngles()
DrawAngles:RotateAroundAxis(self:GetAngles():Forward(), 90)
DrawAngles:RotateAroundAxis(self:GetAngles():Up(), 90)
local backgroundColor = self:GetBackgroundColor() * 255
local barColor = self:GetBarColor() * 255
local topText = DarkRP.textWrap(self:GetTopText(), self.HeaderFont, self.Width - self.BodyMargin * 2)
local bottomText = string.gsub(string.gsub(self:GetBottomText() or "", "//", "\n"), "\\n", "\n")
bottomText = DarkRP.textWrap(string.Replace(bottomText, "\\n", "\n"), self.BodyFont, self.Width - self.BodyMargin * 2)
if not self.HeaderFontHeight then self.HeaderFontHeight = draw.GetFontHeight(self.HeaderFont) end
local barHeight = 1
for _ in string.gmatch(topText, "\n") do barHeight = barHeight + 1 end
barHeight = self.HeaderMargin * 2 + barHeight * self.HeaderFontHeight
local centerX = self.Width / 2
render.EnableClipping(true)
local normal = self:GetUp()
render.PushCustomClipPlane(normal, normal:Dot(DrawPos - normal * self.Height * 0.4))
cam.Start3D2D(DrawPos, DrawAngles, 0.4)
surface.SetDrawColor(backgroundColor.x, backgroundColor.y, backgroundColor.z, 255)
surface.DrawRect(0, 0, self.Width, self.Height)
draw.RoundedBox(0, 0, 0, self.Width, barHeight, Color(barColor.x, barColor.y, barColor.z))
draw.DrawText(topText, self.HeaderFont, centerX, self.HeaderMargin, color_white, TEXT_ALIGN_CENTER)
draw.DrawText(bottomText, self.BodyFont, centerX, barHeight + self.BodyMargin, color_white, TEXT_ALIGN_CENTER)
cam.End3D2D()
render.PopCustomClipPlane()
render.EnableClipping(false)
end
language.Add("Cleaned_advert_billboards", "Cleaned up Advert Billboards")
language.Add("Cleanup_advert_billboards", "Advert Billboards")
language.Add("Undone_advert_billboard", "Undone Advert Billboard")

View File

@@ -0,0 +1,100 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")
function ENT:Initialize()
self:SetModel(self.Model or "models/props/cs_assault/billboard.mdl")
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
self:SetCollisionGroup(COLLISION_GROUP_WORLD)
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:EnableMotion(false)
end
end
function ENT:SetDefaults(txt)
txt = string.gsub(string.gsub(txt or "", "//", "\n"), "\\n", "\n")
local split = string.Split(txt, "\n") or {}
local hasTitle = #split > 1
if not hasTitle then split = string.Split(txt, " ") end
self:SetTopText(split[1] or "Placeholder")
self:SetBottomText(table.concat(split, hasTitle and "\n" or " ", 2))
self:SetBarColor(Vector(1, 0.5, 0))
end
local function canEditVariable(self, ent, ply, key, val, editor)
if self ~= ent then return end
return self:CPPICanPhysgun(ply)
end
local function placeBillboard(ply, args)
local canEdit, message = hook.Call("canAdvert", nil, ply, args)
if canEdit == false then
DarkRP.notify(ply, 1, 4, message or DarkRP.getPhrase("unable", GAMEMODE.Config.chatCommandPrefix .. "advert", ""))
return ""
end
ply.DarkRP_advertboards = ply.DarkRP_advertboards or 0
if ply.DarkRP_advertboards >= GAMEMODE.Config.maxadvertbillboards then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("limit", GAMEMODE.Config.chatCommandPrefix .. "advert"))
return ""
end
local trace = {}
trace.start = ply:EyePos()
trace.endpos = trace.start + ply:GetAimVector() * 85
trace.filter = ply
local tr = util.TraceLine(trace)
local ent = ents.Create("darkrp_billboard")
ent:SetPos(tr.HitPos + Vector(0, 0, (ply:GetPos().z - tr.HitPos.z) + 69))
local ang = ply:GetAngles()
ang:RotateAroundAxis(ang:Up(), 180)
ent:SetAngles(ang)
ent:CPPISetOwner(ply)
ent.SID = ply.SID
ent:SetDefaults(args)
hook.Add("CanEditVariable", ent, canEditVariable)
ent:Spawn()
ent:Activate()
if IsValid(ent) then
ply.DarkRP_advertboards = ply.DarkRP_advertboards + 1
end
ply:DeleteOnRemove(ent)
undo.Create("advert_billboard")
undo.SetPlayer(ply)
undo.AddEntity(ent)
undo.Finish()
ply:AddCleanup("advert_billboards", ent)
hook.Call("playerAdverted", nil, ply, args, ent)
return ""
end
DarkRP.defineChatCommand("advert", placeBillboard)
function ENT:OnRemove()
local ply = Player(self.SID)
if not IsValid(ply) then return end
ply.DarkRP_advertboards = (ply.DarkRP_advertboards or 1) - 1
end

View File

@@ -0,0 +1,113 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "DarkRP billboard"
ENT.Instructions = "Shows advertisements."
ENT.Author = "FPtje"
ENT.Spawnable = false
ENT.Editable = true
ENT.IsDarkRPBillboard = true
cleanup.Register("advert_billboards")
function ENT:SetupDataTables()
self:NetworkVar("String", 0, "TopText", {
KeyName = "toptext",
Edit = {
type = "Generic",
title = "Top text",
category = "Text",
order = 0
}
})
self:NetworkVar("String", 1, "BottomText", {
KeyName = "bottomtext",
Edit = {
type = "Generic",
title = "Bottom text",
category = "Text",
order = 1
}
})
self:NetworkVar("Vector", 0, "BackgroundColor", {
KeyName = "backgroundcolor",
Edit = {
type = "VectorColor",
title = "Background color",
category = "Color",
order = 0
}
})
self:NetworkVar("Vector", 1, "BarColor", {
KeyName = "barcolor",
Edit = {
type = "VectorColor",
title = "Top bar color",
category = "Color",
order = 1
}
})
end
DarkRP.declareChatCommand{
command = "advert",
description = "Create a billboard holding an advertisement.",
delay = 1.5
}
DarkRP.hookStub{
name = "canAdvert",
description = "Whether someone can place an advertisement billboard.",
parameters = {
{
name = "player",
description = "The player trying to advertise.",
type = "Player"
},
{
name = "arguments",
description = "The advertisement itself.",
type = "table"
}
},
returns = {
{
name = "canAdvert",
description = "A yes or no as to whether the player can place the billboard.",
type = "boolean"
},
{
name = "message",
description = "The message that is shown when they can't place the billboard.",
type = "string"
}
},
realm = "Server"
}
DarkRP.hookStub{
name = "playerAdverted",
description = "Called when a player placed an advertisement billboard.",
parameters = {
{
name = "player",
description = "The player.",
type = "Player"
},
{
name = "arguments",
description = "The advertisement itself.",
type = "string"
},
{
name = "entity",
description = "The placed advertisement billboard.",
type = "Entity"
}
},
returns = {},
realm = "Server"
}

View File

@@ -0,0 +1,31 @@
include("shared.lua")
ENT.TextColors = {
OtherToSelf = Color(0, 255, 0, 255),
SelfToSelf = Color(255, 255, 0, 255),
SelfToOther = Color(0, 0, 255, 255),
OtherToOther = Color(255, 0, 0, 255)
}
function ENT:Draw()
self:DrawModel()
local owner = self:Getowning_ent()
local recipient = self:Getrecipient()
local ownerplayer = owner:IsPlayer()
local recipientplayer = recipient:IsPlayer()
local localplayer = LocalPlayer()
local Pos = self:GetPos()
local Ang = self:GetAngles()
local Up = Ang:Up()
Up:Mul(0.9)
Pos:Add(Up)
surface.SetFont("ChatFont")
local text = DarkRP.getPhrase("cheque_pay", recipientplayer and recipient:Nick() or DarkRP.getPhrase("unknown")) .. "\n" .. DarkRP.formatMoney(self:Getamount()) .. "\n" .. DarkRP.getPhrase("signed", ownerplayer and owner:Nick() or DarkRP.getPhrase("unknown"))
cam.Start3D2D(Pos, Ang, 0.1)
draw.DrawNonParsedText(text, "ChatFont", surface.GetTextSize(text) * -0.5, -25, localplayer:IsValid() and (ownerplayer and localplayer == owner and (recipientplayer and localplayer == recipient and self.TextColors.SelfToSelf or self.TextColors.SelfToOther) or recipientplayer and localplayer == recipient and self.TextColors.OtherToSelf) or self.TextColors.OtherToOther, 0)
cam.End3D2D()
end

View File

@@ -0,0 +1,147 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")
function ENT:Initialize()
self:SetModel("models/props_lab/clipboard.mdl")
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
self:SetUseType(SIMPLE_USE)
self.nodupe = true
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:Wake()
end
hook.Add("PlayerDisconnected", self, self.onPlayerDisconnected)
end
function ENT:Use(activator, caller)
local canUse, reason = hook.Call("canDarkRPUse", nil, activator, self, caller)
if canUse == false then
if reason then DarkRP.notify(activator, 1, 4, reason) end
return
end
local owner = self:Getowning_ent()
local recipient = self:Getrecipient()
local amount = self:Getamount() or 0
if (IsValid(activator) and IsValid(recipient)) and activator == recipient then
owner = (IsValid(owner) and owner:Nick()) or DarkRP.getPhrase("disconnected_player")
DarkRP.notify(activator, 0, 4, DarkRP.getPhrase("found_cheque", DarkRP.formatMoney(amount), "", owner))
activator:addMoney(amount)
hook.Call("playerPickedUpCheque", nil, activator, recipient, amount or 0, true, self)
self:Remove()
elseif (IsValid(owner) and IsValid(recipient)) and owner ~= activator then
DarkRP.notify(activator, 0, 4, DarkRP.getPhrase("cheque_details", recipient:Nick()))
hook.Call("playerPickedUpCheque", nil, activator, recipient, amount or 0, false, self)
elseif IsValid(owner) and owner == activator then
DarkRP.notify(activator, 0, 4, DarkRP.getPhrase("cheque_torn"))
owner:addMoney(self:Getamount()) -- return the money on the cheque to the owner.
hook.Call("playerToreUpCheque", nil, activator, recipient, amount, self)
self:Remove()
elseif not IsValid(recipient) then self:Remove()
end
end
function ENT:StartTouch(ent)
-- the .USED var is also used in other mods for the same purpose
if ent:GetClass() ~= "darkrp_cheque" or self.USED or ent.USED or self.hasMerged or ent.hasMerged then return end
if ent:Getowning_ent() ~= self:Getowning_ent() then return end
if ent:Getrecipient() ~= self:Getrecipient() then return end
-- Both hasMerged and USED are used by third party mods. Keep both in.
ent.USED = true
ent.hasMerged = true
ent:Remove()
self:Setamount(self:Getamount() + ent:Getamount())
end
function ENT:OnTakeDamage(dmg)
self:TakePhysicsDamage(dmg)
local typ = dmg:GetDamageType()
if bit.band(typ, bit.bor(DMG_FALL, DMG_VEHICLE, DMG_DROWN, DMG_RADIATION, DMG_PHYSGUN)) > 0 then return end
self.USED = true
self.hasMerged = true
self:Remove()
end
function ENT:onPlayerDisconnected(ply)
if self:Getowning_ent() == ply or self:Getrecipient() == ply then
self:Remove()
end
end
DarkRP.hookStub{
name = "playerPickedUpCheque",
description = "Called when a player picks up a cheque.",
parameters = {
{
name = "player",
description = "The player who attempted to pick up the cheque.",
type = "Player"
},
{
name = "player",
description = "The player who the cheque was written to.",
type = "Player"
},
{
name = "amount",
description = "The amount of money the cheque has.",
type = "number"
},
{
name = "success",
description = "Whether the player was allowed to cash the cheque.",
type = "bool"
},
{
name = "entity",
description = "The entity of the cheque.",
type = "Entity"
}
},
returns = {
},
realm = "Server"
}
DarkRP.hookStub{
name = "playerToreUpCheque",
description = "Called when a player tears up a cheque.",
parameters = {
{
name = "player",
description = "The player who tore up the cheque.",
type = "Player"
},
{
name = "player",
description = "The player who the cheque was written to.",
type = "Player"
},
{
name = "amount",
description = "The amount of money the cheque has.",
type = "number"
},
{
name = "entity",
description = "The entity of the cheque.",
type = "Entity"
}
},
returns = {
},
realm = "Server"
}

View File

@@ -0,0 +1,12 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Cheque"
ENT.Author = "Eusion"
ENT.Spawnable = false
ENT.IsDarkRPCheque = true
function ENT:SetupDataTables()
self:NetworkVar("Entity", 0, "owning_ent")
self:NetworkVar("Entity", 1, "recipient")
self:NetworkVar("Int", 0, "amount")
end

View File

@@ -0,0 +1,72 @@
include("shared.lua")
local Laws = {}
ENT.DrawPos = Vector(1, -111, 58)
local color_navy_200 = Color(0, 0, 70, 200)
local color_red = Color(255, 0, 0, 255)
local color_white = color_white
function ENT:Draw()
self:DrawModel()
local DrawPos = self:LocalToWorld(self.DrawPos)
local DrawAngles = self:GetAngles()
DrawAngles:RotateAroundAxis(self:GetAngles():Forward(), 90)
DrawAngles:RotateAroundAxis(self:GetAngles():Up(), 90)
cam.Start3D2D(DrawPos, DrawAngles, 0.4)
surface.SetDrawColor(0, 0, 0, 255)
surface.DrawRect(0, 0, 558, 290)
draw.RoundedBox(4, 0, 0, 558, 30, color_navy_200)
draw.DrawNonParsedSimpleText(DarkRP.getPhrase("laws_of_the_land"), "Roboto20", 279, 5, color_red, TEXT_ALIGN_CENTER)
local lastHeight = 0
for k, v in ipairs(Laws) do
draw.DrawNonParsedText(string.format("%u. %s", k, v), "Roboto20", 5, 35 + lastHeight, color_white)
lastHeight = lastHeight + (fn.ReverseArgs(string.gsub(v, "\n", "")) + 1) * 21
end
cam.End3D2D()
end
local function addLaw(inLaw)
local law = DarkRP.textWrap(inLaw, "Roboto20", 522)
local lawNumber = table.insert(Laws, law)
hook.Run("addLaw", lawNumber, inLaw)
end
local function umAddLaw(um)
local law = um:ReadString()
timer.Simple(0, fn.Curry(addLaw, 2)(law))
end
usermessage.Hook("DRP_AddLaw", umAddLaw)
local function umRemoveLaw(um)
local i = um:ReadShort()
local removed = table.remove(Laws, i)
hook.Run("removeLaw", i, removed)
end
usermessage.Hook("DRP_RemoveLaw", umRemoveLaw)
local function umResetLaws(um)
Laws = {}
fn.Foldl(function(val,v) addLaw(v) end, nil, GAMEMODE.Config.DefaultLaws)
hook.Run("resetLaws")
end
usermessage.Hook("DRP_ResetLaws", umResetLaws)
function DarkRP.getLaws()
return Laws
end
timer.Simple(0, function()
fn.Foldl(function(val,v) addLaw(v) end, nil, GAMEMODE.Config.DefaultLaws)
end)

View File

@@ -0,0 +1,193 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")
local Laws = {}
local FixedLaws = {}
timer.Simple(0, function()
Laws = table.Copy(GAMEMODE.Config.DefaultLaws)
FixedLaws = table.Copy(Laws)
end)
local hookCanEditLaws = {canEditLaws = function(_, ply, action, args)
if IsValid(ply) and (not RPExtraTeams[ply:Team()] or not RPExtraTeams[ply:Team()].mayor) then
return false, DarkRP.getPhrase("incorrect_job", GAMEMODE.Config.chatCommandPrefix .. action)
end
return true
end}
function ENT:Initialize()
self:SetModel("models/props/cs_assault/Billboard.mdl")
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:EnableMotion(false)
end
end
local function addLaw(ply, args)
local canEdit, message = hook.Call("canEditLaws", hookCanEditLaws, ply, "addLaw", args)
if not canEdit then
DarkRP.notify(ply, 1, 4, message ~= nil and message or DarkRP.getPhrase("unable", GAMEMODE.Config.chatCommandPrefix .. "addLaw", ""))
return ""
end
if not args or args == "" then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("invalid_x", DarkRP.getPhrase("arguments"), ""))
return ""
end
if string.len(args) < 3 then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("law_too_short"))
return ""
end
if #Laws >= 12 then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("laws_full"))
return ""
end
local num = table.insert(Laws, args)
umsg.Start("DRP_AddLaw")
umsg.String(args)
umsg.End()
hook.Run("addLaw", num, args, ply)
DarkRP.notify(ply, 0, 2, DarkRP.getPhrase("law_added"))
return ""
end
DarkRP.defineChatCommand("addLaw", addLaw)
local function removeLaw(ply, args)
local canEdit, message = hook.Call("canEditLaws", hookCanEditLaws, ply, "removeLaw", args)
if not canEdit then
DarkRP.notify(ply, 1, 4, message ~= nil and message or DarkRP.getPhrase("unable", GAMEMODE.Config.chatCommandPrefix .. "removeLaw", ""))
return ""
end
local i = DarkRP.toInt(args)
if not i or not Laws[i] then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("invalid_x", DarkRP.getPhrase("arguments"), ""))
return ""
end
if FixedLaws[i] then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("default_law_change_denied"))
return ""
end
local law = Laws[i]
table.remove(Laws, i)
umsg.Start("DRP_RemoveLaw")
umsg.Short(i)
umsg.End()
hook.Run("removeLaw", i, law, ply)
DarkRP.notify(ply, 0, 2, DarkRP.getPhrase("law_removed"))
return ""
end
DarkRP.defineChatCommand("removeLaw", removeLaw)
function DarkRP.resetLaws()
Laws = table.Copy(FixedLaws)
umsg.Start("DRP_ResetLaws")
umsg.End()
end
local function resetLaws(ply, args)
local canEdit, message = hook.Call("canEditLaws", hookCanEditLaws, ply, "resetLaws", args)
if not canEdit then
DarkRP.notify(ply, 1, 4, message ~= nil and message or DarkRP.getPhrase("unable", GAMEMODE.Config.chatCommandPrefix .. "resetLaws", ""))
return ""
end
hook.Run("resetLaws", ply)
DarkRP.resetLaws()
DarkRP.notify(ply, 0, 2, DarkRP.getPhrase("law_reset"))
return ""
end
DarkRP.defineChatCommand("resetLaws", resetLaws)
local numlaws = 0
local function placeLaws(ply, args)
local canEdit, message = hook.Call("canEditLaws", hookCanEditLaws, ply, "placeLaws", args)
if not canEdit then
DarkRP.notify(ply, 1, 4, message ~= nil and message or DarkRP.getPhrase("unable", GAMEMODE.Config.chatCommandPrefix .. "placeLaws", ""))
return ""
end
if numlaws >= GAMEMODE.Config.maxlawboards then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("limit", GAMEMODE.Config.chatCommandPrefix .. "placeLaws"))
return ""
end
local trace = {}
trace.start = ply:EyePos()
trace.endpos = trace.start + ply:GetAimVector() * 85
trace.filter = ply
local tr = util.TraceLine(trace)
local ent = ents.Create("darkrp_laws")
ent:SetPos(tr.HitPos + Vector(0, 0, 100))
local ang = ply:GetAngles()
ang:RotateAroundAxis(ang:Up(), 180)
ent:SetAngles(ang)
ent:CPPISetOwner(ply)
ent.SID = ply.SID
ent:Spawn()
ent:Activate()
if IsValid(ent) then
numlaws = numlaws + 1
end
ply.lawboards = ply.lawboards or {}
table.insert(ply.lawboards, ent)
return ""
end
DarkRP.defineChatCommand("placeLaws", placeLaws)
function ENT:OnRemove()
numlaws = numlaws - 1
end
hook.Add("PlayerInitialSpawn", "SendLaws", function(ply)
for i, law in ipairs(Laws) do
if FixedLaws[i] then continue end
umsg.Start("DRP_AddLaw", ply)
umsg.String(law)
umsg.End()
end
end)
function DarkRP.getLaws()
return Laws
end

View File

@@ -0,0 +1,161 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "DarkRP Laws"
ENT.Instructions = "Use /addlaws to add a custom law, /removelaw <num> to remove a law."
ENT.Author = "Drakehawke"
ENT.Spawnable = false
local plyMeta = FindMetaTable("Player")
DarkRP.declareChatCommand{
command = "addlaw",
description = "Add a law to the laws board.",
delay = 1.5,
condition = plyMeta.isMayor
}
DarkRP.declareChatCommand{
command = "removelaw",
description = "Remove a law from the laws board.",
delay = 1.5,
condition = plyMeta.isMayor
}
DarkRP.declareChatCommand{
command = "placelaws",
description = "Place a laws board.",
delay = 1.5
}
DarkRP.declareChatCommand{
command = "resetlaws",
description = "Reset all laws.",
delay = 1.5
}
DarkRP.getLaws = DarkRP.stub{
name = "getLaws",
description = "Get the table of all current laws.",
parameters = {
},
returns = {
{
name = "laws",
description = "A table of all current laws.",
type = "table"
}
},
metatable = DarkRP,
realm = "Shared"
}
DarkRP.resetLaws = DarkRP.stub{
name = "resetLaws",
description = "Reset to default laws.",
parameters = {
},
returns = {
},
metatable = DarkRP,
realm = "Server"
}
DarkRP.hookStub{
name = "addLaw",
description = "Called when a law is added.",
parameters = {
{
name = "index",
description = "Index of the law",
type = "number"
},
{
name = "law",
description = "Law string",
type = "string"
},
{
name = "player",
description = "The player who added the law",
type = "Player"
}
},
returns = {
},
realm = "Shared"
}
DarkRP.hookStub{
name = "removeLaw",
description = "Called when a law is removed.",
parameters = {
{
name = "index",
description = "Index of law",
type = "number"
},
{
name = "law",
description = "Law string",
type = "string"
},
{
name = "player",
description = "The player who removed the law",
type = "Player"
}
},
returns = {
},
realm = "Shared"
}
DarkRP.hookStub{
name = "resetLaws",
description = "Called when laws are reset.",
parameters = {
{
name = "player",
description = "The player resetting the laws.",
type = "Player"
}
},
returns = {
},
realm = "Shared"
}
DarkRP.hookStub{
name = "canEditLaws",
description = "Whether someone can edit laws.",
parameters = {
{
name = "player",
description = "The player trying to edit laws.",
type = "Player"
},
{
name = "action",
description = "How the player is trying to edit laws.",
type = "string"
},
{
name = "arguments",
description = "Arguments related to editing laws.",
type = "table"
}
},
returns = {
{
name = "canEdit",
description = "A yes or no as to whether the player can edit the law.",
type = "boolean"
},
{
name = "message",
description = "The message that is shown when they can't edit the law.",
type = "string"
}
},
realm = "Server"
}

View File

@@ -0,0 +1,137 @@
include("shared.lua")
function ENT:Initialize()
self:initVars()
self:initVarsClient()
end
function ENT:initVarsClient()
self.colorBackground = Color(140, 0, 0, 100)
self.colorText = color_white
self.donateAnimColor = Color(20, 100, 20)
self.rotationSpeed = 130
self.rotationOffset = 0
self:InitCsModel()
self.firstDonateAnimation = nil
self.lastDonateAnimation = nil
self.donateAnimSpeed = 0.3
end
function ENT:InitCsModel()
self.csModel = ClientsideModel(self.model)
self.csModel:SetPos(self:GetPos())
self.csModel:SetParent(self)
self.csModel:SetModelScale(1.5, 0)
self.csModel:SetNoDraw(true)
self:CallOnRemove("csModel", fp{SafeRemoveEntity, self.csModel})
end
function ENT:Draw()
local Pos = self:GetPos()
local Ang = self:GetAngles()
local sysTime = SysTime()
local eyepos = EyePos()
local planeNormal = Ang:Up()
local rotAng = Angle(Ang)
self.rotationOffset = sysTime % 360 * self.rotationSpeed
rotAng:RotateAroundAxis(planeNormal, self.rotationOffset)
-- Something about cs models getting removed on their own...
if not IsValid(self.csModel) then
self:InitCsModel()
end
self.csModel:SetPos(Pos)
self.csModel:SetAngles(rotAng)
if not self:IsDormant() then
self.csModel:DrawModel()
end
local owner = self:Getowning_ent()
owner = (IsValid(owner) and owner:Nick()) or DarkRP.getPhrase("unknown")
local title = DarkRP.getPhrase("tip_jar")
surface.SetFont("HUDNumber5")
local titleTextWidth, titleTextHeight = surface.GetTextSize(title)
local ownerTextWidth = surface.GetTextSize(owner)
Ang:RotateAroundAxis(Ang:Forward(), 90)
-- The text can be considered to be "standing" on a plane with normal =
-- Ang:Up(). The vector towards the player's EyePos is projected onto that
-- plane, normalised and rotated to have the text face the user.
local relativeEye = eyepos - Pos
local relativeEyeOnPlane = relativeEye - planeNormal * relativeEye:Dot(planeNormal)
local textAng = relativeEyeOnPlane:AngleEx(planeNormal)
textAng:RotateAroundAxis(textAng:Up(), 90)
textAng:RotateAroundAxis(textAng:Forward(), 90)
cam.Start3D2D(Pos - Ang:Right() * 11.5 , textAng, 0.2)
draw.WordBox(2, -titleTextWidth * 0.5, -72 , title, "HUDNumber5", self.colorBackground, self.colorText)
draw.WordBox(2, -ownerTextWidth * 0.5, -72 + titleTextHeight + 4, owner, "HUDNumber5", self.colorBackground, self.colorText)
self:DrawAnims(sysTime)
cam.End3D2D()
end
function ENT:DrawAnims(sysTime)
local anim = self.firstDonateAnimation
while anim do
if anim.progress > 1 then
anim = anim.nextDonateAnimation
self.firstDonateAnimation = anim
continue
end
draw.SimpleText(
anim.amount,
"DarkRP_tipjar",
-anim.textWidth / 2,
-100 - anim.progress * 200,
ColorAlpha(self.donateAnimColor, Lerp(anim.progress, 1024, 0)),
0
)
anim.progress = (sysTime - anim.start) * self.donateAnimSpeed
anim = anim.nextDonateAnimation
end
if not self.firstDonateAnimation then
self.lastDonateAnimation = nil
end
end
function ENT:Donated(ply, amount)
local txtAmount = DarkRP.formatMoney(amount)
surface.SetFont("DarkRP_tipjar")
local anim = {
amount = txtAmount,
start = SysTime(),
textWidth = surface.GetTextSize(txtAmount),
progress = 0,
nextDonateAnimation = nil,
}
if self.lastDonateAnimation then
self.lastDonateAnimation.nextDonateAnimation = anim
else
self.firstDonateAnimation = anim
end
self.lastDonateAnimation = anim
self:AddDonation(ply:Nick(), amount)
end
-- Disable halos
function ENT:Think() end

View File

@@ -0,0 +1,46 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")
function ENT:Initialize()
self:initVars()
self:SetModel(self.model)
self:SetModelScale(1.5, 0)
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetUseType(SIMPLE_USE)
self:SetSolid(SOLID_VPHYSICS)
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:Wake()
end
self:Activate()
self.nodupe = true
end
function ENT:OnTakeDamage(dmg)
self:TakePhysicsDamage(dmg)
self.damage = (self.damage or 100) - dmg:GetDamage()
if self.damage <= 0 then
self:Remove()
end
end
function ENT:Use(activator, caller)
local canUse, reason = hook.Call("canDarkRPUse", nil, activator, self, caller)
if canUse == false then
if reason then DarkRP.notify(activator, 1, 4, reason) end
return
end
net.Start("DarkRP_TipJarUI")
net.WriteEntity(self)
net.Send(activator)
end

View File

@@ -0,0 +1,80 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Tip Jar"
ENT.Author = "FPtje"
ENT.Spawnable = false
ENT.IsTipjar = true
function ENT:initVars()
self.model = "models/props_lab/jar01a.mdl"
self.damage = 100
self.callOnRemoveId = "tipjar_activedonation_" .. self:EntIndex() .. "_"
self.activeDonations = {}
self.madeDonations = {}
self.PlayerUse = true
end
function ENT:SetupDataTables()
self:NetworkVar("Entity", 0, "owning_ent")
end
function ENT:UpdateActiveDonation(ply, amount)
local old = self.activeDonations[ply]
self.activeDonations[ply] = amount
self:PruneActiveDonations()
ply:CallOnRemove(self.callOnRemoveId .. ply:UserID(), function()
if not IsValid(self) then return end
self:ExitActiveDonation(ply)
end)
hook.Call("tipjarUpdateActiveDonation", DarkRP.hooks, self, ply, amount, old)
end
function ENT:ExitActiveDonation(ply)
local old = self.activeDonations[ply]
self.activeDonations[ply] = nil
self:PruneActiveDonations()
hook.Call("tipjarExitActiveDonation", DarkRP.hooks, self, ply, old)
self:RemoveCallOnRemove(self.callOnRemoveId .. ply:UserID())
end
function ENT:ClearActiveDonations()
table.Empty(self.activeDonations)
hook.Call("tipjarClearActiveDonation", DarkRP.hooks, self)
end
function ENT:PruneActiveDonations()
for ply, _ in pairs(self.activeDonations) do
if not IsValid(ply) then self.activeDonations[ply] = nil end
end
end
function ENT:AddDonation(name, amount)
local lastDonation = self.madeDonations[#self.madeDonations]
if lastDonation and lastDonation.name == name then
lastDonation.amount = lastDonation.amount + amount
else
table.insert(self.madeDonations, {
name = name,
amount = amount,
})
end
-- Enforce maximum of 100 donations
while #self.madeDonations > 100 do
table.remove(self.madeDonations, 1)
end
end
function ENT:ClearDonations()
table.Empty(self.madeDonations)
end

View File

@@ -0,0 +1,53 @@
include("shared.lua")
function ENT:Initialize()
end
local color_red = Color(140, 0, 0, 100)
local color_white = color_white
function ENT:Draw()
self:DrawModel()
local Pos = self:GetPos()
local Ang = self:GetAngles()
local owner = self:Getowning_ent()
owner = (IsValid(owner) and owner:Nick()) or DarkRP.getPhrase("unknown")
surface.SetFont("HUDNumber5")
local text = DarkRP.getPhrase("drugs")
local text2 = DarkRP.getPhrase("priceTag", DarkRP.formatMoney(self:Getprice()), "")
local TextWidth = surface.GetTextSize(text)
local TextWidth2 = surface.GetTextSize(text2)
Ang:RotateAroundAxis(Ang:Forward(), 90)
local TextAng = Ang
TextAng:RotateAroundAxis(TextAng:Right(), CurTime() * -180)
cam.Start3D2D(Pos + Ang:Right() * -15, TextAng, 0.1)
draw.WordBox(2, -TextWidth * 0.5 + 5, -30, text, "HUDNumber5", color_red, color_white)
draw.WordBox(2, -TextWidth2 * 0.5 + 5, 18, text2, "HUDNumber5", color_red, color_white)
cam.End3D2D()
end
function ENT:Think()
end
local function drugEffects(um)
local toggle = um:ReadBool()
LocalPlayer().isDrugged = toggle
if toggle then
hook.Add("RenderScreenspaceEffects", "drugged", function()
DrawSharpen(-1, 2)
DrawMaterialOverlay("models/props_lab/Tank_Glass001", 0)
DrawMotionBlur(0.13, 1, 0.00)
end)
else
hook.Remove("RenderScreenspaceEffects", "drugged")
end
end
usermessage.Hook("DrugEffects", drugEffects)

View File

@@ -0,0 +1,105 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")
local function UnDrugPlayer(ply)
if not IsValid(ply) then return end
ply.isDrugged = false
local IDSteam = ply:SteamID64()
timer.Remove(IDSteam .. "DruggedHealth")
SendUserMessage("DrugEffects", ply, false)
end
hook.Add("PlayerDeath", "UndrugPlayers", function(ply) if ply.isDrugged then UnDrugPlayer(ply) end end)
local function DrugPlayer(ply)
if not IsValid(ply) then return end
SendUserMessage("DrugEffects", ply, true)
ply.isDrugged = true
local IDSteam = ply:SteamID64()
if not timer.Exists(IDSteam .. "DruggedHealth") then
ply:SetHealth(ply:Health() + 100)
timer.Create(IDSteam .. "DruggedHealth", 60 / (100 + 5), 100 + 5, function()
if not IsValid(ply) then return end
ply:SetHealth(ply:Health() - 1)
if ply:Health() <= 0 then
ply:Kill()
end
if timer.RepsLeft(IDSteam .. "DruggedHealth") == 0 then
UnDrugPlayer(ply)
end
end)
end
end
function ENT:Initialize()
self:SetModel("models/props_lab/jar01a.mdl")
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
self.CanUse = true
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:Wake()
end
self.damage = 10
self:Setprice(self:Getprice() or 100)
self.SeizeReward = GAMEMODE.Config.pricemin or 35
end
function ENT:OnTakeDamage(dmg)
self:TakePhysicsDamage(dmg)
self.damage = self.damage - dmg:GetDamage()
if self.damage <= 0 then
local effectdata = EffectData()
effectdata:SetOrigin(self:GetPos())
effectdata:SetMagnitude(2)
effectdata:SetScale(2)
effectdata:SetRadius(3)
util.Effect("Sparks", effectdata)
self:Remove()
end
end
function ENT:Use(activator, caller)
if not self.CanUse then return end
local Owner = self:Getowning_ent()
if not IsValid(Owner) then return end
local canUse, reason = hook.Call("canDarkRPUse", nil, activator, self, caller)
if canUse == false then
if reason then DarkRP.notify(activator, 1, 4, reason) end
return
end
if activator ~= Owner then
if not activator:canAfford(self:Getprice()) then return end
DarkRP.payPlayer(activator, Owner, self:Getprice())
DarkRP.notify(activator, 0, 4, DarkRP.getPhrase("you_bought", DarkRP.getPhrase("drugs"), DarkRP.formatMoney(self:Getprice()), ""))
DarkRP.notify(Owner, 0, 4, DarkRP.getPhrase("you_received_x", DarkRP.formatMoney(self:Getprice()), DarkRP.getPhrase("drugs")))
end
DrugPlayer(caller)
self.CanUse = false
self:Remove()
end
function ENT:OnRemove()
local ply = self:Getowning_ent()
if not IsValid(ply) then return end
ply.maxDrugs = ply.maxDrugs - 1
end

View File

@@ -0,0 +1,23 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Drugs"
ENT.Author = "Rickster"
ENT.Spawnable = false
function ENT:SetupDataTables()
self:NetworkVar("Int", 0, "price")
self:NetworkVar("Entity", 1, "owning_ent")
end
hook.Add("Move", "DruggedPlayer", function(ply, mv)
if not ply.isDrugged then return end
mv:SetMaxSpeed(mv:GetMaxSpeed() * 2)
mv:SetMaxClientSpeed(mv:GetMaxClientSpeed() * 2)
if ply:IsOnGround() and mv:KeyPressed(IN_JUMP) then
local vec = mv:GetVelocity()
vec.z = 100 -- Adds on to the jump power
mv:SetVelocity(vec)
end
end)

View File

@@ -0,0 +1,40 @@
AddCSLuaFile("shared.lua")
include("shared.lua")
DEFINE_BASECLASS("lab_base")
ENT.SeizeReward = 350
ENT.SpawnOffset = Vector(0, 0, 35)
function ENT:Initialize()
BaseClass.Initialize(self)
self.SID = self:Getowning_ent().SID
end
function ENT:SalePrice(activator)
return math.random(math.Round(self:Getprice() / 8), math.Round(self:Getprice() / 4))
end
function ENT:canUse(activator)
if activator.maxDrugs and activator.maxDrugs >= GAMEMODE.Config.maxdrugs then
DarkRP.notify(activator, 1, 3, DarkRP.getPhrase("limit", self.itemPhrase))
return false
end
return true
end
function ENT:createItem(activator)
local drugPos = self:GetPos() + self.SpawnOffset
local drug = ents.Create("drug")
drug:SetPos(drugPos)
drug:Setowning_ent(activator)
drug.SID = activator.SID
drug.nodupe = true
drug:Setprice(self:Getprice() or self.initialPrice)
drug:Spawn()
if not activator.maxDrugs then
activator.maxDrugs = 0
end
activator.maxDrugs = activator.maxDrugs + 1
end

View File

@@ -0,0 +1,11 @@
ENT.Base = "lab_base"
ENT.PrintName = "Drug Lab"
function ENT:initVars()
self.model = "models/props_lab/crematorcase.mdl"
self.initialPrice = GAMEMODE.Config.druglabdrugcost
self.labPhrase = DarkRP.getPhrase("drug_lab")
self.itemPhrase = DarkRP.getPhrase("drugs")
self.noIncome = true
self.camMul = -39
end

View File

@@ -0,0 +1,52 @@
AddCSLuaFile("shared.lua")
include("shared.lua")
function ENT:Initialize()
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:EnableMotion(false)
end
self.SolidPos = self:GetPos()
self.SolidAng = self:GetAngles()
end
function ENT:SetCanRemove(bool)
self.CanRemove = bool
end
function ENT:OnRemove()
if FAdmin.shuttingDown or self.CanRemove or not IsValid(self.target) then return end
local Replace = ents.Create("fadmin_jail")
if (not Replace:IsValid()) then return end
Replace:SetPos(self.SolidPos)
Replace:SetAngles(self.SolidAng)
Replace:SetModel(self:GetModel())
Replace:Spawn()
Replace:Activate()
Replace.target = self.target
Replace.targetPos = self.targetPos
self.target.FAdminJailProps = self.target.FAdminJailProps or {}
self.target.FAdminJailProps[self] = nil
self.target.FAdminJailProps[Replace] = true
if self.targetPos then self.target:SetPos(self.targetPos) end -- Back in jail you! :V
end
function ENT:Think()
if not IsValid(self.target) then
self:SetCanRemove(true)
self:Remove()
return
end
end

View File

@@ -0,0 +1,13 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "fadmin_jail"
ENT.Author = "FPtje"
ENT.Spawnable = false
function ENT:CanTool()
return false
end
function ENT:PhysgunPickup(ply)
return false
end

View File

@@ -0,0 +1,182 @@
include("shared.lua")
local defaultHTML
-- I love the garry's mod wiki!
-- Credits to whoever made this function!
local function WorldToScreen(vWorldPos, vPos, vScale, aRot)
vWorldPos = vWorldPos - vPos
vWorldPos:Rotate(Angle(0, -aRot.y, 0))
vWorldPos:Rotate(Angle(-aRot.p, 0, 0))
vWorldPos:Rotate(Angle(0, 0, -aRot.r))
return vWorldPos.x / vScale, (-vWorldPos.y) / vScale
end
function ENT:LoadPage()
local Page = self.MOTDPage:GetString()
if string.lower(Page) == "data/fadmin/motd.txt" or string.lower(Page) == "default" then
self.HTML:SetHTML(defaultHTML)
elseif string.lower(string.sub(Page, -4)) == ".txt" and string.lower(string.sub(Page, 1, 5)) == "data/" then -- If it's a text file somewhere in data...
Page = string.sub(Page, 6)
self.HTML:SetHTML(file.Read(Page, "DATA") or "")
else
self.HTML:OpenURL(Page)
end
end
function ENT:Initialize()
self.MOTDPage = GetConVar("_FAdmin_MOTDPage")
self.Disabled = true
self.LastDrawn = CurTime()
self.HTML = self.HTMLControl or vgui.Create("HTML")
self.HTML:SetPaintedManually(false)
self.HTML:SetPos(-512, -256)
self.HTMLWidth = 1448
self.HTMLHeight = 724
self.HTML:SetSize(self.HTMLWidth, self.HTMLHeight)
self:LoadPage()
self.HTML:SetVisible(false)
self.HTML:SetKeyboardInputEnabled(false)
timer.Simple(0, function() -- Fix areas of the FAdmin scoreboard coming unclickable
self.HTML:SetPaintedManually(true)
end)
end
function ENT:Think()
if not self.HTML or self.Disabled or self.HTMLCloseButton then
self.HTMLMat = nil
else
self.HTML:UpdateHTMLTexture()
self.HTMLMat = self.HTML:GetHTMLMaterial()
end
self:NextThink(CurTime() + 0.1)
end
local gripTexture = surface.GetTextureID("sprites/grip")
local ArrowTexture = surface.GetTextureID("gui/arrow")
local color_white = color_white
local color_darkgrey = Color(100, 100, 100, 255)
function ENT:Draw()
self:DrawModel()
local pos = self:GetPos()
local ply = LocalPlayer()
if pos:DistToSqr(ply:GetShootPos()) > 90000 then return end
if CurTime() - self.LastDrawn > 0.5 then
self.Disabled = true --Disable it again when you stop looking at it
end
self.LastDrawn = CurTime()
local IsAdmin = ply:IsAdmin()
local HasPhysgun = ply:GetActiveWeapon():IsValid() and ply:GetActiveWeapon():GetClass() == "weapon_physgun"
local isUsing = (HasPhysgun and ply:KeyDown(IN_ATTACK)) or ply:KeyDown(IN_USE)
surface.SetFont("Roboto20")
local TextPosX = surface.GetTextSize("Physgun/use the button to see the MOTD!") * (-0.5)
local ang = self:GetAngles()
ang:RotateAroundAxis(ang:Right(), -90)
ang:RotateAroundAxis(ang:Up(), 90)
local posX, posY = WorldToScreen(ply:GetEyeTrace().HitPos, self:GetPos() + ang:Up() * 3, 0.25, ang)
render.SuppressEngineLighting(true)
cam.Start3D2D(self:GetPos() + ang:Up() * 3, ang, 0.25)
if self.Disabled then
surface.SetDrawColor(0, 0, 0, 255)
surface.DrawRect(-512, 256, 1024, -512)
surface.SetTextColor(255, 255, 255, 255)
surface.SetTextPos(TextPosX, 0)
surface.DrawNonParsedText("Physgun/use the button to see the MOTD!")
draw.WordBox(4, -16, 24, "Click!", "default", color_darkgrey, color_white)
surface.SetDrawColor(255, 255, 255, 255)
if IsAdmin and HasPhysgun then
surface.SetTexture(gripTexture)
surface.DrawTexturedRect(-10, 240, 16, 16)
end
if isUsing then
posX, posY = math.Clamp(posX, -506, 506), math.Clamp(posY, -250, 250)
surface.SetTexture(ArrowTexture)
surface.DrawTexturedRectRotated(posX + 5, posY + 5, 16, 16, 45)
-- Clicking button
if posX > -16 and posX < 16 and posY > 24 and posY < 48 then
self:LoadPage()
self.Disabled = false
self.CanClickAgain = CurTime() + 1
end
end
elseif not self.HTMLMat then
self.HTML:SetVisible(true)
self.HTML:SetKeyboardInputEnabled(true)
self.HTML:SetPaintedManually(false)
self.HTML:UpdateHTMLTexture()
timer.Simple(0, function() -- Fix HTML material
self.HTML:SetPaintedManually(true)
self.HTML:SetVisible(false)
self.HTML:SetKeyboardInputEnabled(false)
end)
else
surface.SetMaterial(self.HTMLMat)
surface.SetDrawColor(255, 255, 255, 255)
surface.DrawTexturedRect(-512, -256, self.HTMLWidth, self.HTMLHeight)
end
cam.End3D2D()
render.SuppressEngineLighting(false)
if self.HTMLCloseButton then return end
--Drawing the actual HTML panel:
if isUsing and posX > -500 and posX < 500 and posY < 250 and posY > -250 and
not self.Disabled and self.HTML and self.HTML:IsValid() and self.CanClickAgain and CurTime() > self.CanClickAgain then
self.CanClickAgain = CurTime() + 1
self.HTML:SetPaintedManually(false)
self.HTML:SetPos(0, 100)
self.HTML:SetSize(ScrW(), ScrH() - 100)
gui.EnableScreenClicker(true)
-- gui.SetMousePos(posX/1024*ScrW(), posY/512*(ScrH() - 100) + 100)
self.HTMLCloseButton = self.HTMLCloseButton or vgui.Create("DButton")
self.HTMLCloseButton:SetPos(ScrW() - 100, 0)
self.HTMLCloseButton:SetSize(100, 100)
self.HTMLCloseButton:SetText("X")
self.HTMLCloseButton:SetVisible(true)
self.HTML:SetVisible(true)
self.HTML:RequestFocus()
self.HTML:SetKeyboardInputEnabled(true)
self.HTML:MakePopup()
function self.HTMLCloseButton.DoClick() -- Revert to drawing on the prop
self.HTML:SetPos(-512, -256)
self.HTML:SetSize(self.HTMLWidth, self.HTMLHeight)
self.HTML:SetPaintedManually(true)
self.HTML:SetKeyboardInputEnabled(false)
self.HTML:SetVisible(false)
gui.EnableScreenClicker(false)
self.HTMLCloseButton:Remove()
self.HTMLCloseButton = nil
end
end
end
defaultHTML = [[
<html>
<title>MOTD!</title>
<body bgcolor="888888">
<center><h1>Example MOTD/Instructions on how to set a proper MOTD</h1></center>
<h2>Of course you have to be superadmin or owner.</h2>
<ol>
<li>Copy the website URL to the clipboard<br></li>
<li>Enter the command: FAdmin MOTDPage "your website here"<br><br></li>
<i>Example:</i><br>
FAdmin MOTDPage "www.facepunch.com"
</body>
</html>]]

View File

@@ -0,0 +1,54 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")
function ENT:Initialize()
self:SetModel("models/props_wasteland/interior_fence002d.mdl")
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:EnableMotion(false)
end
self.SolidPos = self:GetPos()
self.SolidAng = self:GetAngles()
self:SetMaterial("models/props_lab/warp_sheet")
end
function ENT:OnRemove()
if not self.CanRemove and IsValid(self.target) then
local Replace = ents.Create("fadmin_motd")
Replace:SetPos(self.SolidPos)
Replace:SetAngles(self.SolidAng)
Replace:Spawn()
Replace:SetModel(self:GetModel())
end
end
function ENT:OnPhysgunFreeze(Weapon, PhysObj, ent, ply)
FAdmin.MOTD.SaveMOTD(ent, ply)
end
function ENT:SpawnFunction(ply, tr)
if not tr.Hit then return end
for _, v in ipairs(ents.FindByClass("fadmin_motd")) do
v.CanRemove = true
v:Remove() --There can only be one motd per level
end
local SpawnPos = tr.HitPos + tr.HitNormal * 16 + Vector(0,0,50)
local ent = ents.Create("fadmin_motd")
ent:SetPos(SpawnPos)
local Ang = ply:EyeAngles()
ent:SetAngles(Angle(0, Ang.y-180, Ang.r))
ent:Spawn()
ent:Activate()
end

View File

@@ -0,0 +1,21 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "fadmin MOTD"
ENT.Information = "Place this MOTD somewhere, freeze it and it will be saved automatically"
ENT.Author = "FPtje"
ENT.Spawnable = false
function ENT:CanTool(ply, trace, tool)
if ply:IsAdmin() and tool == "remover" then
self.CanRemove = true
if SERVER then FAdmin.MOTD.RemoveMOTD(self, ply) end
return true
end
return false
end
local PickupPos = Vector(1.8079, -0.6743, -62.3193)
function ENT:PhysgunPickup(ply)
if ply:IsAdmin() and PickupPos:DistToSqr(self:WorldToLocal(ply:GetEyeTrace().HitPos)) < 49 then return true end
return false
end

View File

@@ -0,0 +1,54 @@
AddCSLuaFile("shared.lua")
include("shared.lua")
function ENT:Initialize()
self:SetModel("models/props_junk/garbage_takeoutcarton001a.mdl")
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:Wake()
end
self.damage = 10
end
function ENT:OnTakeDamage(dmg)
self:TakePhysicsDamage(dmg)
self.damage = self.damage - dmg:GetDamage()
if (self.damage <= 0) then
local effectdata = EffectData()
effectdata:SetOrigin(self:GetPos())
effectdata:SetMagnitude(2)
effectdata:SetScale(2)
effectdata:SetRadius(3)
util.Effect("Sparks", effectdata)
self:Remove()
end
end
function ENT:Use(activator, caller)
local canUse, reason = hook.Call("canDarkRPUse", nil, activator, self, caller)
if canUse == false then
if reason then DarkRP.notify(activator, 1, 4, reason) end
return
end
caller:setSelfDarkRPVar("Energy", 100)
umsg.Start("AteFoodIcon", caller)
umsg.End()
self:Remove()
activator:EmitSound(self.EatSound, 100, 100)
end
function ENT:OnRemove()
local ply = self:Getowning_ent()
ply.maxFoods = ply.maxFoods and ply.maxFoods - 1 or 0
end

View File

@@ -0,0 +1,10 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Food"
ENT.Author = "Pcwizdan"
ENT.Spawnable = false
ENT.EatSound = "vo/sandwicheat09.mp3" -- Requires Team Fortress 2
function ENT:SetupDataTables()
self:NetworkVar("Entity", 1, "owning_ent")
end

View File

@@ -0,0 +1,17 @@
AddCSLuaFile("shared.lua")
include("shared.lua")
ENT.SpawnOffset = Vector(0, 0, 27)
function ENT:createItem()
local gun = ents.Create("spawned_weapon")
local wep = weapons.Get(GAMEMODE.Config.gunlabweapon)
gun:SetModel(wep and wep.WorldModel or "models/weapons/w_pist_p228.mdl")
gun:SetWeaponClass(GAMEMODE.Config.gunlabweapon)
local gunPos = self:GetPos() + self.SpawnOffset
gun:SetPos(gunPos)
gun.nodupe = true
gun:Spawn()
end

View File

@@ -0,0 +1,9 @@
ENT.Base = "lab_base"
ENT.PrintName = "Gun Lab"
function ENT:initVars()
self.model = "models/props_c17/TrapPropeller_Engine.mdl"
self.initialPrice = GAMEMODE.Config.gunlabguncost
self.labPhrase = DarkRP.getPhrase("gun_lab")
self.itemPhrase = DarkRP.getPhrase("gun")
end

View File

@@ -0,0 +1,34 @@
include("shared.lua")
function ENT:Initialize()
self:initVars()
end
local color_red = Color(140, 0, 0, 100)
local color_white = color_white
function ENT:DrawTranslucent()
self:DrawModel()
local Pos = self:GetPos()
local Ang = self:GetAngles()
local owner = self:Getowning_ent()
owner = (IsValid(owner) and owner:Nick()) or DarkRP.getPhrase("unknown")
surface.SetFont("HUDNumber5")
local text = self.labPhrase
local text2 = DarkRP.getPhrase("priceTag", DarkRP.formatMoney(self:Getprice()), "")
local TextWidth = surface.GetTextSize(text)
local TextWidth2 = surface.GetTextSize(text2)
Ang:RotateAroundAxis(Ang:Forward(), 90)
local TextAng = Ang
TextAng:RotateAroundAxis(TextAng:Right(), CurTime() * -180)
cam.Start3D2D(Pos + Ang:Right() * self.camMul, TextAng, 0.2)
draw.WordBox(2, -TextWidth * 0.5 + 5, -30, text, "HUDNumber5", color_red, color_white)
draw.WordBox(2, -TextWidth2 * 0.5 + 5, 18, text2, "HUDNumber5", color_red, color_white)
cam.End3D2D()
end

View File

@@ -0,0 +1,149 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")
function ENT:Initialize()
self:initVars()
self:SetModel(self.model)
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
self:SetUseType(SIMPLE_USE)
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:Wake()
end
self.sparking = false
self.damage = 100
self:Setprice(math.Clamp(self.initialPrice, (GAMEMODE.Config.pricemin ~= 0 and GAMEMODE.Config.pricemin) or self.initialPrice, (GAMEMODE.Config.pricecap ~= 0 and GAMEMODE.Config.pricecap) or self.initialPrice))
end
function ENT:OnTakeDamage(dmg)
self:TakePhysicsDamage(dmg)
self.damage = self.damage - dmg:GetDamage()
if self.damage <= 0 and not self.Destructed then
self.Destructed = true
self:Destruct()
self:Remove()
end
end
function ENT:Destruct()
local vPoint = self:GetPos()
util.BlastDamage(self, self, vPoint, self.blastRadius, self.blastDamage)
util.ScreenShake(vPoint, 512, 255, 1.5, 200)
local effectdata = EffectData()
effectdata:SetStart(vPoint)
effectdata:SetOrigin(vPoint)
effectdata:SetScale(1)
util.Effect(self:WaterLevel() > 1 and "WaterSurfaceExplosion" or "Explosion", effectdata)
util.Decal("Scorch", vPoint, vPoint - Vector(0, 0, 25), self)
end
function ENT:SalePrice(activator)
local owner = self:Getowning_ent()
if activator == owner then
if self.allowed and istable(self.allowed) and table.HasValue(self.allowed, activator:Team()) then
return math.ceil(self:Getprice() * 0.8)
else
return math.ceil(self:Getprice() * 0.9)
end
else
return self:Getprice()
end
end
ENT.Once = false
function ENT:Use(activator, caller)
-- The lab cannot be used by non-players (e.g. wire user)
-- The player must be known for the lab to work.
if not activator:IsPlayer() then return end
if self.Once then return end
local owner = self:Getowning_ent()
if not IsValid(owner) then
DarkRP.notify(activator, 1, 3, DarkRP.getPhrase("disabled", self.labPhrase, DarkRP.getPhrase("disconnected_player")))
return
end
local cost = self:SalePrice(activator)
if not activator:canAfford(cost) then
DarkRP.notify(activator, 1, 3, DarkRP.getPhrase("cant_afford", self.itemPhrase))
return
end
local diff = cost - self:SalePrice(owner)
if not self.noIncome and diff < 0 and not owner:canAfford(math.abs(diff)) then
DarkRP.notify(activator, 1, 3, DarkRP.getPhrase("owner_poor", self.labPhrase))
return
end
if not self:canUse(activator) then return end
local canUse, reason = hook.Call("canDarkRPUse", nil, activator, self, caller)
if canUse == false then
if reason then DarkRP.notify(activator, 1, 4, reason) end
return
end
self.Once = true
self.sparking = true
activator:addMoney(-cost)
DarkRP.notify(activator, 0, 3, DarkRP.getPhrase("you_bought", self.itemPhrase, DarkRP.formatMoney(cost)))
if activator ~= owner and not self.noIncome then
if diff == 0 then
DarkRP.notify(owner, 0, 3, DarkRP.getPhrase("you_received_x", DarkRP.formatMoney(0) .. " " .. DarkRP.getPhrase("profit"), self.itemPhrase))
else
owner:addMoney(diff)
local word = DarkRP.getPhrase("profit")
if diff < 0 then word = DarkRP.getPhrase("loss") end
DarkRP.notify(owner, 0, 3, DarkRP.getPhrase("you_received_x", DarkRP.formatMoney(math.abs(diff)) .. " " .. word, self.itemPhrase))
end
end
timer.Create(self:EntIndex() .. self.itemPhrase, 1, 1, function()
if not IsValid(self) then return end
if IsValid(activator) then
self:createItem(activator)
end
self.Once = false
self.sparking = false
end)
end
function ENT:canUse(owner, activator)
return true
end
function ENT:createItem(activator)
-- Implement this function
end
function ENT:Think()
if self.sparking then
local effectdata = EffectData()
effectdata:SetOrigin(self:GetPos())
effectdata:SetMagnitude(1)
effectdata:SetScale(1)
effectdata:SetRadius(2)
util.Effect("Sparks", effectdata)
end
end
function ENT:OnRemove()
timer.Remove(self:EntIndex() .. self.itemPhrase)
end

View File

@@ -0,0 +1,27 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Lab"
ENT.Author = "DarkRP Developers"
ENT.Spawnable = false
ENT.CanSetPrice = true
-- These are variables that should be set in entities that base from this
ENT.model = ""
ENT.initialPrice = 0
ENT.labPhrase = ""
ENT.itemPhrase = ""
ENT.noIncome = false
ENT.camMul = -30
ENT.blastRadius = 200
ENT.blastDamage = 200
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
function ENT:initVars()
-- Implement this to set the above variables
end
function ENT:SetupDataTables()
self:NetworkVar("Int", 0, "price")
self:NetworkVar("Entity", 1, "owning_ent")
end

View File

@@ -0,0 +1,76 @@
include("shared.lua")
local frame
local SignButton
function ENT:Draw()
self:DrawModel()
end
local function KillLetter(msg)
hook.Remove("HUDPaint", "ShowLetter")
frame:Remove()
end
usermessage.Hook("KillLetter", KillLetter)
local function ShowLetter(msg)
if frame then
frame:Remove()
end
local LetterMsg = ""
local Letter = msg:ReadEntity()
local LetterType = msg:ReadShort()
local LetterPos = msg:ReadVector()
local sectionCount = msg:ReadShort()
local LetterY = ScrH() / 2 - 300
local LetterAlpha = 255
Letter:CallOnRemove("Kill letter HUD on remove", KillLetter)
for k = 1, sectionCount, 1 do
LetterMsg = LetterMsg .. msg:ReadString()
end
frame = vgui.Create("DFrame")
frame:SetTitle("")
frame:ShowCloseButton(false)
SignButton = vgui.Create("DButton", frame)
SignButton:SetText(DarkRP.getPhrase("sign_this_letter"))
frame:SetPos(ScrW() - 256, ScrH() - 256)
SignButton:SetSize(256, 256)
frame:SetSize(256, 256)
SignButton:SetSkin(GAMEMODE.Config.DarkRPSkin)
frame:SizeToContents()
frame:MakePopup()
frame:SetKeyboardInputEnabled(false)
function SignButton:DoClick()
RunConsoleCommand("_DarkRP_SignLetter", Letter:EntIndex())
SignButton:SetDisabled(true)
end
SignButton:SetDisabled(IsValid(Letter:Getsigned()))
hook.Add("HUDPaint", "ShowLetter", function()
if not Letter.dt then KillLetter() return end
if LetterAlpha < 255 then
LetterAlpha = math.Clamp(LetterAlpha + 400 * FrameTime(), 0, 255)
end
local font = (LetterType == 1 and "AckBarWriting") or "Default"
draw.RoundedBox(2, ScrW() * .2, LetterY, ScrW() * .8 - (ScrW() * .2), ScrH(), Color(255, 255, 255, math.Clamp(LetterAlpha, 0, 200)))
draw.DrawNonParsedText(LetterMsg .. "\n\n\n" .. DarkRP.getPhrase("signed", IsValid(Letter:Getsigned()) and Letter:Getsigned():Nick() or DarkRP.getPhrase("no_one")), font, ScrW() * .25 + 20, LetterY + 80, Color(0, 0, 0, LetterAlpha), 0)
if LocalPlayer():GetPos():DistToSqr(LetterPos) > 10000 then
LetterY = Lerp(0.1, LetterY, ScrH())
LetterAlpha = Lerp(0.1, LetterAlpha, 0)
if frame and frame.Close then frame:Close() end
if math.Round(LetterAlpha) <= 10 then
KillLetter()
end
end
end)
end
usermessage.Hook("ShowLetter", ShowLetter)

View File

@@ -0,0 +1,94 @@
local function MakeLetter(ply, args, type)
if not GAMEMODE.Config.letters then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("disabled", "/write / /type", ""))
return ""
end
if ply.maxletters and ply.maxletters >= GAMEMODE.Config.maxletters then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("limit", "letter"))
return ""
end
if CurTime() - ply:GetTable().LastLetterMade < 3 then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("have_to_wait", math.ceil(3 - (CurTime() - ply:GetTable().LastLetterMade)), "/write / /type"))
return ""
end
ply:GetTable().LastLetterMade = CurTime()
-- Instruct the player's letter window to open
local ftext = string.gsub(args, "//", "\n")
ftext = string.gsub(ftext, "\\n", "\n") .. "\n\n" .. DarkRP.getPhrase("signed_yours") .. "\n" .. ply:Nick()
local length = string.len(ftext)
local numParts = math.floor(length / 39) + 1
local trace = {}
trace.start = ply:EyePos()
trace.endpos = trace.start + ply:GetAimVector() * 85
trace.filter = ply
local tr = util.TraceLine(trace)
local letter = ents.Create("letter")
letter:SetModel("models/props_c17/paper01.mdl")
letter:SetPos(tr.HitPos)
letter:Setowning_ent(ply)
letter.nodupe = true
letter:Spawn()
letter:GetTable().Letter = true
letter.type = type
letter.numPts = numParts
DarkRP.placeEntity(letter, tr, ply)
local startpos = 1
local endpos = 39
letter.Parts = {}
for k = 1, numParts, 1 do
table.insert(letter.Parts, string.sub(ftext, startpos, endpos))
startpos = startpos + 39
endpos = endpos + 39
end
letter.SID = ply.SID
DarkRP.printMessageAll(2, DarkRP.getPhrase("created_x", ply:Nick(), "mail"))
if not ply.maxletters then
ply.maxletters = 0
end
ply.maxletters = ply.maxletters + 1
timer.Simple(600, function() if IsValid(letter) then letter:Remove() end end)
end
local function WriteLetter(ply, args)
if args == "" then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("invalid_x", DarkRP.getPhrase("arguments"), ""))
return ""
end
MakeLetter(ply, args, 1)
return ""
end
DarkRP.defineChatCommand("write", WriteLetter)
local function TypeLetter(ply, args)
if args == "" then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("invalid_x", DarkRP.getPhrase("arguments"), ""))
return ""
end
MakeLetter(ply, args, 2)
return ""
end
DarkRP.defineChatCommand("type", TypeLetter)
local function RemoveLetters(ply)
for k, v in ipairs(ents.FindByClass("letter")) do
if v.SID == ply.SID then v:Remove() end
end
DarkRP.notify(ply, 4, 4, DarkRP.getPhrase("cleaned_up", "mails"))
return ""
end
DarkRP.defineChatCommand("removeletters", RemoveLetters)

View File

@@ -0,0 +1,98 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")
include("commands.lua")
function ENT:Initialize()
self:SetModel("models/props_c17/paper01.mdl")
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
self:SetUseType(SIMPLE_USE)
self:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE_DEBRIS)
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:Wake()
end
hook.Add("PlayerDisconnected", self, self.onPlayerDisconnected)
end
function ENT:OnTakeDamage(dmg)
self:TakePhysicsDamage(dmg)
local typ = dmg:GetDamageType()
if bit.band(typ, bit.bor(DMG_FALL, DMG_VEHICLE, DMG_DROWN, DMG_RADIATION, DMG_PHYSGUN)) > 0 then return end
self:Remove()
end
function ENT:OnRemove()
local ply = self:Getowning_ent()
if not IsValid(ply) then return end
if not ply.maxletters then
ply.maxletters = 0
end
ply.maxletters = ply.maxletters - 1
end
function ENT:Use(ply)
if not ply:KeyDown(IN_ATTACK) then
umsg.Start("ShowLetter", ply)
umsg.Entity(self)
umsg.Short(self.type)
umsg.Vector(self:GetPos())
local numParts = self.numPts
umsg.Short(numParts)
for _, b in ipairs(self.Parts) do umsg.String(b) end
umsg.End()
else
umsg.Start("KillLetter", ply)
umsg.End()
end
end
function ENT:SignLetter(ply)
self:Setsigned(ply)
end
function ENT:onPlayerDisconnected(ply)
if self:Getowning_ent() == ply then
self:Remove()
end
end
concommand.Add("_DarkRP_SignLetter", function(ply, cmd, args)
if not args[1] or ply:EntIndex() == 0 then return end
local letter = ents.GetByIndex(tonumber(args[1]))
if not IsValid(letter) or letter:GetClass() ~= "letter" then return end
letter:SignLetter(ply)
end)
local function removeLetters(ply, args)
local target = DarkRP.findPlayer(args)
if target then
for _, v in ipairs(ents.FindByClass("letter")) do
if v.SID == target.SID then v:Remove() end
end
else
-- Remove ALL letters
for _, v in ipairs(ents.FindByClass("letter")) do
v:Remove()
end
end
if ply:EntIndex() == 0 then
DarkRP.log("Console force-removed all letters", Color(30, 30, 30))
else
DarkRP.log(ply:Nick() .. " (" .. ply:SteamID() .. ") force-removed all letters", Color(30, 30, 30))
end
DarkRP.notify(ply, 0, 4, "All letters removed")
end
DarkRP.definePrivilegedChatCommand("removeletters", "DarkRP_AdminCommands", removeLetters)

View File

@@ -0,0 +1,28 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "letter"
ENT.Author = "Pcwizdan"
ENT.Spawnable = false
function ENT:SetupDataTables()
self:NetworkVar("Entity",1,"owning_ent")
self:NetworkVar("Entity",2,"signed")
end
DarkRP.declareChatCommand{
command = "write",
description = "Write a letter.",
delay = 5
}
DarkRP.declareChatCommand{
command = "type",
description = "Type a letter.",
delay = 5
}
DarkRP.declareChatCommand{
command = "removeletters",
description = "Remove all of your letters.",
delay = 5
}

View File

@@ -0,0 +1,36 @@
ENT.Spawnable = false
ENT.AdminSpawnable = false
include("shared.lua")
language.Add("meteor", "meteor")
function ENT:Initialize()
local mx, mn = self:GetRenderBounds()
self:SetRenderBounds(mn + Vector(0,0,128), mx, 0)
self.emitter = ParticleEmitter(LocalPlayer():GetShootPos())
end
local color_grey = Color(200, 200, 210)
function ENT:Think()
local vOffset = self:LocalToWorld(VectorRand(-3, 3)) + VectorRand(-3, 3)
local vNormal = (vOffset - self:GetPos()):GetNormalized()
if not self.emitter then return end
local particle = self.emitter:Add(Model("particles/smokey"), vOffset)
particle:SetVelocity(vNormal * math.Rand(10, 30))
particle:SetDieTime(2.0)
particle:SetStartAlpha(math.Rand(50, 150))
particle:SetStartSize(math.Rand(8, 16))
particle:SetEndSize(math.Rand(32, 64))
particle:SetRoll(math.Rand(-0.2, 0.2))
particle:SetColor(color_grey)
end
function ENT:OnRemove()
if IsValid(self.emitter) then
self.emitter:Finish()
end
end

View File

@@ -0,0 +1,69 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")
function ENT:Initialize()
self:SetModel("models/props_junk/Rock001a.mdl")
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
self:Ignite(20, 0)
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:Wake()
end
phys:EnableMotion(true)
phys:SetMass(1000)
phys:EnableGravity(false)
end
function ENT:SetMeteorTarget(ent)
local foundSky = util.IsInWorld(ent:GetPos())
local zPos = ent:GetPos().z
for a = 1, 30, 1 do
zPos = zPos + 100
foundSky = util.IsInWorld(Vector(ent:GetPos().x ,ent:GetPos().y ,zPos))
if (foundSky == false) then
zPos = zPos - 120
break
end
end
self:SetPos(Vector(ent:GetPos().x + math.random(-4000,4000),ent:GetPos().y + math.random(-4000,4000), zPos))
local speed = 100000000
local VNormal = (Vector(ent:GetPos().x + math.random(-500,500),ent:GetPos().y + math.random(-500,500),ent:GetPos().z) - self:GetPos()):GetNormal()
self:GetPhysicsObject():ApplyForceCenter(VNormal * speed)
end
function ENT:Destruct(notexplode)
if not notexplode then
util.BlastDamage(self, self, self:GetPos(), 200, 60)
end
self:Extinguish()
local vPoint = self:GetPos()
local effectdata = EffectData()
effectdata:SetStart(vPoint)
effectdata:SetOrigin(vPoint)
effectdata:SetScale(1)
util.Effect("Explosion", effectdata)
-- You get warnings about changing collision rule when removing immediately
-- https://github.com/FPtje/DarkRP/issues/2832
timer.Simple(0, fp{SafeRemoveEntity, self})
end
function ENT:OnTakeDamage(dmg)
if (dmg:GetDamage() > 5) then
self:Destruct(true)
end
end
function ENT:PhysicsCollide(data, physobj)
if data.HitEntity:GetClass() == "func_breakable_surf" then self:Remove() return end
self:Destruct()
end

View File

@@ -0,0 +1,6 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Meteor"
ENT.Author = "Rickster"
ENT.Contact = "Rickyman35@hotmail.com"
ENT.Spawnable = false

View File

@@ -0,0 +1,26 @@
AddCSLuaFile("shared.lua")
include("shared.lua")
ENT.SpawnOffset = Vector(0, 0, 23)
function ENT:canUse(activator)
if activator.maxFoods and activator.maxFoods >= GAMEMODE.Config.maxfoods then
DarkRP.notify(activator, 1, 3, DarkRP.getPhrase("limit", self.itemPhrase))
return false
end
return true
end
function ENT:createItem(activator)
local foodPos = self:GetPos() + self.SpawnOffset
local food = ents.Create("food")
food:SetPos(foodPos)
food:Setowning_ent(activator)
food.nodupe = true
food:Spawn()
if not activator.maxFoods then
activator.maxFoods = 0
end
activator.maxFoods = activator.maxFoods + 1
end

View File

@@ -0,0 +1,9 @@
ENT.Base = "lab_base"
ENT.PrintName = "Microwave"
function ENT:initVars()
self.model = "models/props/cs_office/microwave.mdl"
self.initialPrice = GAMEMODE.Config.microwavefoodcost
self.labPhrase = DarkRP.getPhrase("microwave")
self.itemPhrase = DarkRP.getPhrase("food")
end

View File

@@ -0,0 +1,41 @@
include("shared.lua")
function ENT:Initialize()
self:initVars()
if not self.DisplayName or self.DisplayName == "" then
self.DisplayName = DarkRP.getPhrase("money_printer")
end
end
local camStart3D2D = cam.Start3D2D
local camEnd3D2D = cam.End3D2D
local drawWordBox = draw.WordBox
local IsValid = IsValid
local color_red = Color(140,0,0,100)
local color_white = color_white
function ENT:Draw()
self:DrawModel()
local Pos = self:GetPos()
local Ang = self:GetAngles()
local owner = self:Getowning_ent()
owner = (IsValid(owner) and owner:Nick()) or DarkRP.getPhrase("unknown")
surface.SetFont("HUDNumber5")
local text = self.DisplayName
local TextWidth = surface.GetTextSize(text)
local TextWidth2 = surface.GetTextSize(owner)
Ang:RotateAroundAxis(Ang:Up(), 90)
camStart3D2D(Pos + Ang:Up() * 11.5, Ang, 0.11)
drawWordBox(2, -TextWidth * 0.5, -30, text, "HUDNumber5", color_red, color_white)
drawWordBox(2, -TextWidth2 * 0.5, 18, owner, "HUDNumber5", color_red, color_white)
camEnd3D2D()
end
function ENT:Think()
end

View File

@@ -0,0 +1,144 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")
ENT.SpawnOffset = Vector(15, 0, 15)
local function PrintMore(ent)
if not IsValid(ent) then return end
ent.sparking = true
timer.Simple(3, function()
if not IsValid(ent) then return end
ent:CreateMoneybag()
end)
end
function ENT:StartSound()
self.sound = CreateSound(self, Sound("ambient/levels/labs/equipment_printer_loop1.wav"))
self.sound:SetSoundLevel(52)
self.sound:PlayEx(1, 100)
end
function ENT:PostInit()
--Dumb things what you want to run on printer spawn
end
function ENT:Initialize()
self:initVars()
self:SetModel(self.model)
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:Wake()
end
timer.Simple(math.random(self.MinTimer, self.MaxTimer), function() PrintMore(self) end)
self:StartSound()
self:PostInit()
end
function ENT:OnTakeDamage(dmg)
self:TakePhysicsDamage(dmg)
if self.burningup then return end
self.damage = (self.damage or 100) - dmg:GetDamage()
if self.damage <= 0 then
local rnd = math.random(1, 10)
if rnd < 3 then
self:BurstIntoFlames()
else
self:Destruct()
self:Remove()
end
end
end
function ENT:Destruct()
local vPoint = self:GetPos()
local effectdata = EffectData()
effectdata:SetStart(vPoint)
effectdata:SetOrigin(vPoint)
effectdata:SetScale(1)
util.Effect("Explosion", effectdata)
if IsValid(self:Getowning_ent()) then DarkRP.notify(self:Getowning_ent(), 1, 4, DarkRP.getPhrase("money_printer_exploded")) end
end
function ENT:BurstIntoFlames()
if hook.Run("moneyPrinterCatchFire", self) == true then return end
if IsValid(self:Getowning_ent()) then DarkRP.notify(self:Getowning_ent(), 0, 4, DarkRP.getPhrase("money_printer_overheating")) end
self.burningup = true
local burntime = math.random(8, 18)
self:Ignite(burntime, 0)
timer.Simple(burntime, function() self:Fireball() end)
end
function ENT:Fireball()
if not self:IsOnFire() then self.burningup = false return end
local dist = math.random(20, 280) -- Explosion radius
self:Destruct()
for k, v in ipairs(ents.FindInSphere(self:GetPos(), dist)) do
if not v:IsPlayer() and not v:IsWeapon() and v:GetClass() ~= "predicted_viewmodel" and not v.IsMoneyPrinter then
v:Ignite(math.random(5, 22), 0)
elseif v:IsPlayer() then
local distance = v:GetPos():Distance(self:GetPos())
v:TakeDamage(distance / dist * 100, self, self)
end
end
self:Remove()
end
function ENT:CreateMoneybag()
if self:IsOnFire() then return end
local amount = self.MoneyCount or (GAMEMODE.Config.mprintamount ~= 0 and GAMEMODE.Config.mprintamount or 250)
local prevent, hookAmount = hook.Run("moneyPrinterPrintMoney", self, amount)
if prevent == true then return end
local MoneyPos = self:GetPos() + self.SpawnOffset
amount = hookAmount or amount
if self.OverheatChance and self.OverheatChance > 0 then
local overheatchance
if self.OverheatChance <= 3 then
overheatchance = 22
else
overheatchance = self.OverheatChance or 22
end
if math.random(1, overheatchance) == 3 then self:BurstIntoFlames() end
end
local moneybag = DarkRP.createMoneyBag(MoneyPos, amount)
hook.Run("moneyPrinterPrinted", self, moneybag)
self.sparking = false
timer.Simple(math.random(self.MinTimer, self.MaxTimer), function() PrintMore(self) end)
end
function ENT:Think()
if self:WaterLevel() > 0 then
self:Destruct()
self:Remove()
return
end
self:StartSound()
if not self.sparking then return end
local effectdata = EffectData()
effectdata:SetOrigin(self:GetPos())
effectdata:SetMagnitude(1)
effectdata:SetScale(1)
effectdata:SetRadius(2)
util.Effect("Sparks", effectdata)
end
function ENT:OnRemove()
if self.sound then
self.sound:Stop()
end
end

View File

@@ -0,0 +1,94 @@
--Static Vars
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Money Printer"
ENT.Author = "DarkRP Developers"
ENT.Spawnable = false
ENT.sparking = false
ENT.IsMoneyPrinter = true
function ENT:initVars()
self.MoneyCount = GAMEMODE.Config.mprintamount
self.OverheatChance = GAMEMODE.Config.printeroverheatchance
self.model = "models/props_c17/consolebox01a.mdl"
self.damage = 100
self.DisplayName = "Money Printer"
self.MinTimer = 100
self.MaxTimer = 350
self.SeizeReward = GAMEMODE.Config.printerreward
end
function ENT:SetupDataTables()
self:NetworkVar("Int", 0, "price")
self:NetworkVar("Entity", 0, "owning_ent")
end
DarkRP.hookStub{
name = "moneyPrinterCatchFire",
description = "Called when a money printer is about to catch fire.",
parameters = {
{
name = "moneyprinter",
description = "The money printer that is about to catch fire",
type = "Entity"
}
},
returns = {
{
name = "prevent",
description = "Set to true to prevent the money printer from catching fire",
type = "boolean"
}
},
realm = "Server"
}
DarkRP.hookStub{
name = "moneyPrinterPrintMoney",
description = "Called when a money printer is about to print money.",
parameters = {
{
name = "moneyprinter",
description = "The money printer that is about to print money",
type = "Entity"
},
{
name = "amount",
description = "The amount to be printed",
type = "number"
}
},
returns = {
{
name = "prevent",
description = "Set to true to prevent the money printer from printing the money.",
type = "boolean"
},
{
name = "amount",
description = "Optionally override the amount of money that will be printed.",
type = "number"
}
},
realm = "Server"
}
DarkRP.hookStub{
name = "moneyPrinterPrinted",
description = "Called after a money printer is has printed money.",
parameters = {
{
name = "moneyprinter",
description = "The money printer",
type = "Entity"
},
{
name = "moneybag",
description = "The moneybag produced by the printer.",
type = "Entity"
}
},
returns = {
},
realm = "Server"
}

View File

@@ -0,0 +1,74 @@
AddCSLuaFile("shared.lua")
include("shared.lua")
function ENT:Initialize()
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
self:SetUseType(SIMPLE_USE)
local phys = self:GetPhysicsObject()
phys:Wake()
end
function ENT:Use(activator, caller)
local canUse, reason = hook.Call("canDarkRPUse", nil, activator, self, caller)
if canUse == false then
if reason then DarkRP.notify(activator, 1, 4, reason) end
return
end
hook.Call("playerPickedUpAmmo", nil, activator, self.amountGiven, self.ammoType, self)
activator:GiveAmmo(self.amountGiven, self.ammoType)
self:Remove()
end
function ENT:OnTakeDamage(dmg)
self:TakePhysicsDamage(dmg)
end
function ENT:StartTouch(ent)
-- the .USED var is also used in other mods for the same purpose
if ent.IsSpawnedAmmo ~= true or
self.ammoType ~= ent.ammoType or
self.hasMerged or ent.hasMerged then return end
ent.hasMerged = true
ent.USED = true
local selfAmount, entAmount = self.amountGiven, ent.amountGiven
local totalAmount = selfAmount + entAmount
self.amountGiven = totalAmount
ent:Remove()
end
DarkRP.hookStub{
name = "playerPickedUpAmmo",
description = "When a player picks up ammo.",
parameters = {
{
name = "ply",
description = "The player who picked up ammo.",
type = "Player"
},
{
name = "amount",
description = "Ammo amount.",
type = "number"
},
{
name = "type",
description = "Ammo type.",
type = "number"
},
{
name = "spawnedAmmo",
description = "Entity of spawned ammo.",
type = "Entity"
}
},
returns = {
},
}

View File

@@ -0,0 +1,6 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Spawned Ammo"
ENT.Author = "FPtje"
ENT.Spawnable = false
ENT.IsSpawnedAmmo = true

View File

@@ -0,0 +1,68 @@
AddCSLuaFile("shared.lua")
include("shared.lua")
function ENT:Initialize()
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
self:SetUseType(SIMPLE_USE)
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:Wake()
end
end
function ENT:OnTakeDamage(dmg)
self:Remove()
end
function ENT:Use(activator, caller)
local canUse, reason = hook.Call("canDarkRPUse", nil, activator, self, caller)
if canUse == false then
if reason then DarkRP.notify(activator, 1, 4, reason) end
return
end
local override = self.foodItem.onEaten and self.foodItem.onEaten(self, activator, self.foodItem)
if override then
self:Remove()
return
end
hook.Call("playerAteFood", nil, activator, self.foodItem, self)
activator:setSelfDarkRPVar("Energy", math.Clamp((activator:getDarkRPVar("Energy") or 100) + (self.FoodEnergy or 1), 0, 100))
umsg.Start("AteFoodIcon", activator)
umsg.End()
self:Remove()
activator:EmitSound(self.EatSound, 100, 100)
end
DarkRP.hookStub{
name = "playerAteFood",
description = "When a player eats food.",
parameters = {
{
name = "ply",
description = "The player who ate food.",
type = "Player"
},
{
name = "food",
description = "Food table.",
type = "table"
},
{
name = "spawnedfood",
description = "Entity of spawned food.",
type = "Entity"
},
},
returns = {
},
}

View File

@@ -0,0 +1,11 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Spawned Food"
ENT.Author = "Rickster"
ENT.Spawnable = false
ENT.IsSpawnedFood = true
ENT.EatSound = "vo/sandwicheat09.mp3" -- Requires Team Fortress 2
function ENT:SetupDataTables()
self:NetworkVar("Entity", 1, "owning_ent")
end

View File

@@ -0,0 +1,32 @@
include("shared.lua")
local color_red = Color(140, 0, 0, 100)
local color_white = color_white
function ENT:Draw()
self:DrawModel()
-- Do not draw labels when a different model is used.
-- If you want a different model with labels, make your own money entity and use GM.Config.MoneyClass.
if self:GetModel() ~= "models/props/cs_assault/money.mdl" then return end
local Pos = self:GetPos()
local Ang = self:GetAngles()
surface.SetFont("ChatFont")
local text = DarkRP.formatMoney(self:Getamount())
local TextWidth = surface.GetTextSize(text)
cam.Start3D2D(Pos + Ang:Up() * 0.82, Ang, 0.1)
draw.WordBox(2, -TextWidth * 0.5, -10, text, "ChatFont", color_red, color_white)
cam.End3D2D()
Ang:RotateAroundAxis(Ang:Right(), 180)
cam.Start3D2D(Pos, Ang, 0.1)
draw.WordBox(2, -TextWidth * 0.5, -10, text, "ChatFont", color_red, color_white)
cam.End3D2D()
end
function ENT:Think()
end

View File

@@ -0,0 +1,126 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")
function ENT:Initialize()
self:SetModel(GAMEMODE.Config.moneyModel or "models/props/cs_assault/money.mdl")
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
self:SetUseType(SIMPLE_USE)
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
self.nodupe = true
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:Wake()
end
end
function ENT:Use(activator, caller)
if self.USED or self.hasMerged then return end
local canUse, reason = hook.Call("canDarkRPUse", nil, activator, self, caller)
if canUse == false then
if reason then DarkRP.notify(activator, 1, 4, reason) end
return
end
self.USED = true
local amount = self:Getamount()
hook.Call("playerPickedUpMoney", nil, activator, amount or 0, self)
activator:addMoney(amount or 0)
DarkRP.notify(activator, 0, 4, DarkRP.getPhrase("found_money", DarkRP.formatMoney(self:Getamount())))
self:Remove()
end
function ENT:OnTakeDamage(dmg)
self:TakePhysicsDamage(dmg)
local typ = dmg:GetDamageType()
if bit.band(typ, bit.bor(DMG_FALL, DMG_VEHICLE, DMG_DROWN, DMG_RADIATION, DMG_PHYSGUN)) > 0 then return end
self.USED = true
self.hasMerged = true
self:Remove()
end
function ENT:StartTouch(ent)
-- the .USED var is also used in other mods for the same purpose
if ent:GetClass() ~= "spawned_money" or self.USED or ent.USED or self.hasMerged or ent.hasMerged then return end
-- Both hasMerged and USED are used by third party mods. Keep both in.
ent.USED = true
ent.hasMerged = true
ent:Remove()
self:Setamount(self:Getamount() + ent:Getamount())
if GAMEMODE.Config.moneyRemoveTime and GAMEMODE.Config.moneyRemoveTime ~= 0 then
timer.Adjust("RemoveEnt" .. self:EntIndex(), GAMEMODE.Config.moneyRemoveTime, 1, fn.Partial(SafeRemoveEntity, self))
end
end
DarkRP.hookStub{
name = "playerPickedUpMoney",
description = "Called when a player picked up money.",
parameters = {
{
name = "player",
description = "The player who picked up the money.",
type = "Player"
},
{
name = "amount",
description = "The amount of money picked up.",
type = "number"
},
{
name = "entity",
description = "The entity of the money picked up itself.",
type = "Entity"
}
},
returns = {
},
realm = "Server"
}
DarkRP.hookStub{
name = "canDarkRPUse",
description = "When a player uses an entity.",
parameters = {
{
name = "ply",
description = "The player who tries to use the entity.",
type = "Player"
},
{
name = "entity",
description = "The actual entity the player attempts to use.",
type = "Entity"
},
{
name = "caller",
description = "The entity that directly triggered the input.",
type = "Player"
}
},
returns = {
{
name = "canUse",
description = "Whether the entity should be used or not.",
type = "boolean"
},
{
name = "reason",
description = "Why the entity cannot be used.",
optional = true,
type = "string"
},
},
}

View File

@@ -0,0 +1,10 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Spawned Money"
ENT.Author = "FPtje"
ENT.Spawnable = false
ENT.IsSpawnedMoney = true
function ENT:SetupDataTables()
self:NetworkVar("Int",0,"amount")
end

View File

@@ -0,0 +1,161 @@
include("shared.lua")
local matBallGlow = Material("models/props_combine/tpballglow")
function ENT:Draw()
self.height = self.height or 0
self.colr = self.colr or 1
self.colg = self.colg or 0
self.StartTime = self.StartTime or CurTime()
if GAMEMODE.Config.shipmentspawntime > 0 and self.height < self:OBBMaxs().z then
self:drawSpawning()
else
self:DrawModel()
end
self:drawFloatingGun()
self:drawInfo()
end
net.Receive("DarkRP_shipmentSpawn", function()
local ent = net.ReadEntity()
if not IsValid(ent) or not ent.IsSpawnedShipment then return end
ent.height = 0
ent.StartTime = CurTime()
end)
function ENT:drawSpawning()
render.MaterialOverride(matBallGlow)
render.SetColorModulation(self.colr, self.colg, 0)
self:DrawModel()
render.MaterialOverride()
self.colr = 1 - ((CurTime() - self.StartTime) / GAMEMODE.Config.shipmentspawntime)
self.colg = (CurTime() - self.StartTime) / GAMEMODE.Config.shipmentspawntime
render.SetColorModulation(1, 1, 1)
render.MaterialOverride()
local normal = - self:GetAngles():Up()
local pos = self:LocalToWorld(Vector(0, 0, self:OBBMins().z + self.height))
local distance = normal:Dot(pos)
self.height = self:OBBMaxs().z * ((CurTime() - self.StartTime) / GAMEMODE.Config.shipmentspawntime)
render.EnableClipping(true)
render.PushCustomClipPlane(normal, distance)
self:DrawModel()
render.PopCustomClipPlane()
end
function ENT:drawFloatingGun()
local contents = CustomShipments[self:Getcontents() or ""]
if not contents or not IsValid(self:GetgunModel()) then return end
self:GetgunModel():SetNoDraw(true)
local pos = self:GetPos()
local ang = self:GetAngles()
-- Position the gun
local gunPos = self:GetAngles():Up() * 40 + ang:Up() * (math.sin(CurTime() * 3) * 8)
self:GetgunModel():SetPos(pos + gunPos)
-- Make it dance
ang:RotateAroundAxis(ang:Up(), (CurTime() * 180) % 360)
self:GetgunModel():SetAngles(ang)
-- Draw the model
if self:Getgunspawn() < CurTime() - 2 then
self:GetgunModel():DrawModel()
return
elseif self:Getgunspawn() < CurTime() then -- Not when a gun just spawned
return
end
-- Draw the spawning effect
local delta = self:Getgunspawn() - CurTime()
local min, max = self:GetgunModel():OBBMins(), self:GetgunModel():OBBMaxs()
min, max = self:GetgunModel():LocalToWorld(min), self:GetgunModel():LocalToWorld(max)
-- Draw the ghosted weapon
render.MaterialOverride(matBallGlow)
render.SetColorModulation(1 - delta, delta, 0) -- From red to green
self:GetgunModel():DrawModel()
render.MaterialOverride()
render.SetColorModulation(1, 1, 1)
-- Draw the cut-off weapon
render.EnableClipping(true)
-- The clipping plane only draws objects that face the plane
local normal = -self:GetgunModel():GetAngles():Forward()
local cutPosition = LerpVector(delta, max, min) -- Where it cuts
local cutDistance = normal:Dot(cutPosition) -- Project the vector onto the normal to get the shortest distance between the plane and origin
-- Activate the plane
render.PushCustomClipPlane(normal, cutDistance);
-- Draw the partial model
self:GetgunModel():DrawModel()
-- Remove the plane
render.PopCustomClipPlane()
render.EnableClipping(false)
end
local color_red = Color(140, 0, 0, 100)
local color_white = color_white
function ENT:drawInfo()
local Pos = self:GetPos()
local Ang = self:GetAngles()
local content = self:Getcontents() or ""
local contents = CustomShipments[content]
if not contents then return end
contents = contents.name
surface.SetFont("HUDNumber5")
local text = DarkRP.getPhrase("contents")
local TextWidth = surface.GetTextSize(text)
local TextWidth2 = surface.GetTextSize(contents)
cam.Start3D2D(Pos + Ang:Up() * 25, Ang, 0.2)
draw.WordBox(2, -TextWidth * 0.5 + 5, -30, text, "HUDNumber5", color_red, color_white)
draw.WordBox(2, -TextWidth2 * 0.5 + 5, 18, contents, "HUDNumber5", color_red, color_white)
cam.End3D2D()
Ang:RotateAroundAxis(Ang:Forward(), 90)
text = DarkRP.getPhrase("amount")
TextWidth = surface.GetTextSize(text)
TextWidth2 = surface.GetTextSize(self:Getcount())
cam.Start3D2D(Pos + Ang:Up() * 17, Ang, 0.14)
draw.WordBox(2, -TextWidth * 0.5 + 5, -150, text, "HUDNumber5", color_red, color_white)
draw.WordBox(2, -TextWidth2 * 0.5 + 0, -102, self:Getcount(), "HUDNumber5", color_red, color_white)
cam.End3D2D()
end
--[[---------------------------------------------------------------------------
Create a shipment from a spawned_weapon
---------------------------------------------------------------------------]]
properties.Add("splitShipment",
{
MenuLabel = DarkRP.getPhrase("splitshipment"),
Order = 2004,
MenuIcon = "icon16/arrow_divide.png",
Filter = function(self, ent, ply)
if not IsValid(ent) then return false end
return ent.IsSpawnedShipment
end,
Action = function(self, ent)
if not IsValid(ent) then return end
RunConsoleCommand("darkrp", "splitshipment", ent:EntIndex())
end
})

View File

@@ -0,0 +1,103 @@
--[[---------------------------------------------------------------------------
Create a shipment from a spawned_weapon
---------------------------------------------------------------------------]]
local function createShipment(ply, args)
local id = tonumber(args) or -1
local ent = Entity(id)
ent = IsValid(ent) and ent or ply:GetEyeTrace().Entity
if not IsValid(ent) or not ent.IsSpawnedWeapon or ent.PlayerUse == false then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("invalid_x", DarkRP.getPhrase("arguments"), ""))
return
end
local pos = ent:GetPos()
if pos:DistToSqr(ply:GetShootPos()) > 16900 or not pos:isInSight({ent, ply} , ply) then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("distance_too_big"))
return
end
ent.PlayerUse = false
local shipID
for k, v in pairs(CustomShipments) do
if v.entity == ent:GetWeaponClass() then
shipID = k
break
end
end
if not shipID or ent.USED then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("unable", "/makeshipment", ""))
return
end
local crate = ents.Create(CustomShipments[shipID].shipmentClass or "spawned_shipment")
crate.SID = ply.SID
crate:SetPos(ent:GetPos())
crate.nodupe = true
crate:SetContents(shipID, ent:Getamount())
crate:Spawn()
crate:SetPlayer(ply)
crate.clip1 = ent.clip1
crate.clip2 = ent.clip2
crate.ammoadd = ent.ammoadd or 0
SafeRemoveEntity(ent)
local phys = crate:GetPhysicsObject()
phys:Wake()
end
DarkRP.defineChatCommand("makeshipment", createShipment, 0.3)
--[[---------------------------------------------------------------------------
Split a shipment in two
---------------------------------------------------------------------------]]
local function splitShipment(ply, args)
local id = tonumber(args) or -1
local ent = Entity(id)
ent = IsValid(ent) and ent or ply:GetEyeTrace().Entity
if not IsValid(ent) or not ent.IsSpawnedShipment then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("invalid_x", DarkRP.getPhrase("arguments"), ""))
return
end
if ent:Getcount() < 2 or ent.locked or ent.USED then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("shipment_cannot_split"))
return
end
local pos = ent:GetPos()
if pos:DistToSqr(ply:GetShootPos()) > 16900 or not pos:isInSight({ent, ply} , ply) then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("distance_too_big"))
return
end
local count = math.floor(ent:Getcount() / 2)
ent:Setcount(ent:Getcount() - count)
ent:StartSpawning()
local crate = ents.Create("spawned_shipment")
crate.locked = true
crate.SID = ply.SID
crate:SetPos(ent:GetPos())
crate.nodupe = true
crate:SetContents(ent:Getcontents(), count)
crate:SetPlayer(ply)
crate.clip1 = ent.clip1
crate.clip2 = ent.clip2
crate.ammoadd = ent.ammoadd
crate:Spawn()
local phys = crate:GetPhysicsObject()
phys:Wake()
end
DarkRP.defineChatCommand("splitshipment", splitShipment, 0.3)

View File

@@ -0,0 +1,257 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")
include("commands.lua")
util.AddNetworkString("DarkRP_shipmentSpawn")
function ENT:Initialize()
local contents = CustomShipments[self:Getcontents() or ""]
self.Destructed = false
self:SetModel(contents and contents.shipmodel or "models/Items/item_item_crate.mdl")
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
self:StartSpawning()
self.damage = 100
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:Wake()
end
-- Create a serverside gun model
-- it's required serverside to be able to get OBB information clientside
self:SetgunModel(IsValid(self:GetgunModel()) and self:GetgunModel() or ents.Create("prop_physics"))
self:GetgunModel():SetModel(contents.model)
self:GetgunModel():SetPos(self:GetPos())
self:GetgunModel():Spawn()
self:GetgunModel():Activate()
self:GetgunModel():SetSolid(SOLID_NONE)
self:GetgunModel():SetParent(self)
phys = self:GetgunModel():GetPhysicsObject()
if phys:IsValid() then
phys:EnableMotion(false)
end
-- The following code should not be reached
if self:Getcount() < 1 then
self.PlayerUse = false
SafeRemoveEntity(self)
if not contents then
DarkRP.error("Shipment created with zero or fewer elements.", 2)
else
DarkRP.error(string.format("Some smartass thought they were clever by setting the 'amount' of shipment '%s' to 0.\nWhat the fuck do you expect the use of an empty shipment to be?", contents.name), 2)
end
end
end
function ENT:StartSpawning()
self.locked = true
timer.Simple(0, function()
net.Start("DarkRP_shipmentSpawn")
net.WriteEntity(self)
net.Broadcast()
end)
timer.Simple(0, function() self.locked = true end) -- when spawning through pocket it might be unlocked
timer.Simple(GAMEMODE.Config.shipmentspawntime, function() if IsValid(self) then self.locked = false end end)
end
function ENT:OnTakeDamage(dmg)
self:TakePhysicsDamage(dmg)
if not self.locked then
self.damage = self.damage - dmg:GetDamage()
if self.damage <= 0 then
self:Destruct()
end
end
end
function ENT:SetContents(s, c)
self:Setcontents(s)
self:Setcount(c)
end
function ENT:Use(activator, caller)
if self.IsPocketed then return end
if isfunction(self.PlayerUse) then
local val = self:PlayerUse(activator, caller)
if val ~= nil then return val end
elseif self.PlayerUse ~= nil then
return self.PlayerUse
end
if self.locked or self.USED then return end
local canUse, reason = hook.Call("canDarkRPUse", nil, activator, self, caller)
if canUse == false then
if reason then DarkRP.notify(activator, 1, 4, reason) end
return
end
hook.Call("playerOpenedShipment", nil, activator, self)
self.locked = true -- One activation per second
self.USED = true
self.sparking = true
self:Setgunspawn(CurTime() + 1)
timer.Create(self:EntIndex() .. "crate", 1, 1, function()
if not IsValid(self) then return end
self.SpawnItem(self)
end)
end
local function calculateAmmo(class, shipment)
local clip1, ammoadd = shipment.clip1, shipment.ammoadd
local defaultClip, clipSize = 0, 0
local wep_tbl = weapons.Get(class)
if wep_tbl and istable(wep_tbl.Primary) then
defaultClip = wep_tbl.Primary.DefaultClip or -1
clipSize = wep_tbl.Primary.ClipSize or -1
end
ammoadd = ammoadd or defaultClip
if not clip1 then
clip1 = clipSize
end
return ammoadd, clip1
end
function ENT:SpawnItem()
timer.Remove(self:EntIndex() .. "crate")
self.sparking = false
local count = self:Getcount()
if count <= 1 then self:Remove() end
local contents = self:Getcontents()
if CustomShipments[contents] and CustomShipments[contents].spawn then self.USED = false return CustomShipments[contents].spawn(self, CustomShipments[contents]) end
local weapon = ents.Create("spawned_weapon")
local weaponAng = self:GetAngles()
local weaponPos = self:GetAngles():Up() * 40 + weaponAng:Up() * (math.sin(CurTime() * 3) * 8)
weaponAng:RotateAroundAxis(weaponAng:Up(), (CurTime() * 180) % 360)
if not CustomShipments[contents] then
weapon:Remove()
self:Remove()
return
end
local class = CustomShipments[contents].entity
local model = CustomShipments[contents].model
weapon:SetWeaponClass(class)
weapon:SetModel(model)
weapon.ammoadd, weapon.clip1 = calculateAmmo(class, self)
weapon.clip2 = self.clip2
weapon:SetPos(self:GetPos() + weaponPos)
weapon:SetAngles(weaponAng)
weapon.nodupe = true
weapon:Spawn()
count = count - 1
self:Setcount(count)
self.locked = false
self.USED = nil
end
function ENT:Think()
if self.sparking then
local effectdata = EffectData()
effectdata:SetOrigin(self:GetPos())
effectdata:SetMagnitude(1)
effectdata:SetScale(1)
effectdata:SetRadius(2)
util.Effect("Sparks", effectdata)
end
end
function ENT:Destruct()
if self.Destructed then return end
self.Destructed = true
local vPoint = self:GetPos()
local contents = self:Getcontents()
local count = self:Getcount()
local class = nil
local model = nil
if CustomShipments[contents] then
class = CustomShipments[contents].entity
model = CustomShipments[contents].model
else
self:Remove()
return
end
local weapon = ents.Create("spawned_weapon")
weapon:SetModel(model)
weapon:SetWeaponClass(class)
weapon:SetPos(Vector(vPoint.x, vPoint.y, vPoint.z + 5))
weapon.ammoadd, weapon.clip1 = calculateAmmo(class, self)
weapon.clip2 = self.clip2
weapon.nodupe = true
weapon:Spawn()
weapon:Setamount(count)
self:Remove()
end
function ENT:StartTouch(ent)
-- the .USED var is also used in other mods for the same purpose
if not ent.IsSpawnedShipment or
self:Getcontents() ~= ent:Getcontents() or
self.locked or ent.locked or
self.USED or ent.USED or
self.hasMerged or ent.hasMerged then return end
-- Both hasMerged and USED are used by third party mods. Keep both in.
ent.hasMerged = true
ent.USED = true
local selfCount, entCount = self:Getcount(), ent:Getcount()
local count = selfCount + entCount
self:Setcount(count)
-- Merge ammo information (avoid ammo exploits)
if self.clip1 or ent.clip1 then -- If neither have a clip, use default clip, otherwise merge the two
self.clip1 = math.floor(((ent.clip1 or 0) * entCount + (self.clip1 or 0) * selfCount) / count)
end
if self.clip2 or ent.clip2 then
self.clip2 = math.floor(((ent.clip2 or 0) * entCount + (self.clip2 or 0) * selfCount) / count)
end
if self.ammoadd or ent.ammoadd then
self.ammoadd = math.floor(((ent.ammoadd or 0) * entCount + (self.ammoadd or 0) * selfCount) / count)
end
ent:Remove()
end
DarkRP.hookStub{
name = "playerOpenedShipment",
description = "When a player opens a shipment.",
parameters = {
{
name = "player",
description = "The player who opens a shipment.",
type = "Player"
},
{
name = "entity",
description = "Entity of spawned shipment.",
type = "Entity"
}
},
returns = {
},
}

View File

@@ -0,0 +1,26 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Shipment"
ENT.Author = "philxyz"
ENT.Spawnable = false
ENT.IsSpawnedShipment = true
function ENT:SetupDataTables()
self:NetworkVar("Int",0,"contents")
self:NetworkVar("Int",1,"count")
self:NetworkVar("Float", 0, "gunspawn")
self:NetworkVar("Entity", 0, "owning_ent")
self:NetworkVar("Entity", 1, "gunModel")
end
DarkRP.declareChatCommand{
command = "splitshipment",
description = "Split the shipment you're looking at.",
delay = 1.5
}
DarkRP.declareChatCommand{
command = "makeshipment",
description = "Create a shipment from a dropped weapon.",
delay = 1.5
}

View File

@@ -0,0 +1,76 @@
include("shared.lua")
local color_red = Color(140, 0, 0, 100)
local color_white = color_white
function ENT:Draw()
local ret = hook.Call("onDrawSpawnedWeapon", nil, self)
if ret ~= nil then return end
self:DrawModel()
local amount = self:Getamount()
if amount == 1 then return end
local Pos = self:GetPos()
local Ang = self:GetAngles()
local text = DarkRP.getPhrase("amount") .. amount
surface.SetFont("HUDNumber5")
local TextWidth = surface.GetTextSize(text)
Ang:RotateAroundAxis(Ang:Forward(), 90)
cam.Start3D2D(Pos + Ang:Up(), Ang, 0.11)
draw.WordBox(2, 0, -40, text, "HUDNumber5", color_red, color_white)
cam.End3D2D()
Ang:RotateAroundAxis(Ang:Right(), 180)
cam.Start3D2D(Pos + Ang:Up() * 3, Ang, 0.11)
draw.WordBox(2, -TextWidth, -40, text, "HUDNumber5", color_red, color_white)
cam.End3D2D()
end
--[[---------------------------------------------------------------------------
Create a shipment from a spawned_weapon
---------------------------------------------------------------------------]]
properties.Add("createShipment",
{
MenuLabel = DarkRP.getPhrase("createshipment"),
Order = 2003,
MenuIcon = "icon16/add.png",
Filter = function(self, ent, ply)
if not IsValid(ent) then return false end
return ent.IsSpawnedWeapon
end,
Action = function(self, ent)
if not IsValid(ent) then return end
RunConsoleCommand("darkrp", "makeshipment", ent:EntIndex())
end
}
)
--[[---------------------------------------------------------------------------
Interface
---------------------------------------------------------------------------]]
DarkRP.hookStub{
name = "onDrawSpawnedWeapon",
description = "Draw spawned weapons.",
realm = "Client",
parameters = {
{
name = "weapon",
description = "The weapon to perform drawing operations on.",
type = "Player"
}
},
returns = {
{
name = "value",
description = "Return a value to completely override drawing",
type = "any"
}
}
}

View File

@@ -0,0 +1,163 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")
function ENT:Initialize()
DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS,
string.format("The issue lies with weapon \"%s\"", self:GetWeaponClass() or "unknown"))
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
self:SetUseType(SIMPLE_USE)
local phys = self:GetPhysicsObject()
phys:Wake()
if self:Getamount() == 0 then
self:Setamount(1)
end
end
function ENT:DecreaseAmount()
local amount = self:Getamount() - 1
self:Setamount(amount)
if amount <= 0 then
self:Remove()
self.PlayerUse = false
self.Removed = true -- because it is not removed immediately
end
end
function ENT:OnTakeDamage(dmg)
self:TakePhysicsDamage(dmg)
end
function ENT:Use(activator, caller)
if isfunction(self.PlayerUse) then
local val = self:PlayerUse(activator, caller)
if val ~= nil then return val end
elseif self.PlayerUse ~= nil then
return self.PlayerUse
end
local class = self:GetWeaponClass()
local weapon = ents.Create(class)
if not weapon:IsWeapon() then
weapon:SetPos(self:GetPos())
weapon:SetAngles(self:GetAngles())
weapon:Spawn()
weapon:Activate()
self:DecreaseAmount()
return
end
local CanPickup = hook.Call("PlayerCanPickupWeapon", GAMEMODE, activator, weapon)
local ShouldntContinue = hook.Call("PlayerPickupDarkRPWeapon", nil, activator, self, weapon)
if not CanPickup or ShouldntContinue then
weapon:Remove()
return
end
weapon:Remove()
weapon = activator:Give(class, true)
-- The player already had the weapon when the result of :Give() is not a
-- valid weapon
local activatorHadWeapon = not weapon:IsValid()
weapon = activatorHadWeapon and activator:GetWeapon(class) or weapon
hook.Call("playerPickedUpWeapon", nil, activator, self, weapon)
self:GivePlayerAmmo(activator, weapon, activatorHadWeapon)
self:DecreaseAmount()
end
function ENT:GivePlayerAmmo(ply, weapon, playerHadWeapon)
local primaryAmmoType = weapon:GetPrimaryAmmoType()
local secondaryAmmoType = weapon:GetSecondaryAmmoType()
local clip1, clip2 = self.clip1, self.clip2
if playerHadWeapon then
if clip2 and clip2 > 0 and weapon:Clip2() ~= -1 then
weapon:SetClip2(weapon:Clip2() + clip2)
clip2 = 0
end
else
if clip1 and clip1 ~= -1 and weapon:Clip1() ~= -1 then
weapon:SetClip1(clip1)
clip1 = 0
end
if clip2 and clip2 ~= -1 and weapon:Clip2() ~= -1 then
weapon:SetClip2(self.clip2)
clip2 = 0
end
end
if primaryAmmoType > 0 then
local primAmmo = ply:GetAmmoCount(primaryAmmoType)
primAmmo = primAmmo + (self.ammoadd or 0) + (clip1 or 0) -- Gets rid of any ammo given during weapon pickup
ply:SetAmmo(primAmmo, primaryAmmoType)
end
if secondaryAmmoType > 0 then
local secAmmo = ply:GetAmmoCount(secondaryAmmoType) + (clip2 or 0)
ply:SetAmmo(secAmmo, secondaryAmmoType)
end
end
function ENT:StartTouch(ent)
-- the .USED var is also used in other mods for the same purpose
if ent.IsSpawnedWeapon ~= true or
self:GetWeaponClass() ~= ent:GetWeaponClass() or
self.hasMerged or ent.hasMerged then return end
ent.hasMerged = true
ent.USED = true
local selfAmount, entAmount = self:Getamount(), ent:Getamount()
local totalAmount = selfAmount + entAmount
self.ammoadd, ent.ammoadd = self.ammoadd or 0, ent.ammoadd or 0
-- ammoAdd will be the floored average of both weapons' ammoadd
-- Some ammo might get lost there.
self.ammoadd = math.floor((self.ammoadd * selfAmount + ent.ammoadd * entAmount) / totalAmount)
-- If neither have a clip, use default clip, otherwise merge the two
if self.clip1 or ent.clip1 then
self.clip1 = math.floor(((self.clip1 or 0) * selfAmount + (ent.clip1 or 0) * entAmount) / totalAmount)
end
if self.clip2 or ent.clip2 then
self.clip2 = math.floor(((self.clip2 or 0) * selfAmount + (ent.clip2 or 0) * entAmount) / totalAmount)
end
self:Setamount(totalAmount)
ent:Remove()
end
DarkRP.hookStub{
name = "playerPickedUpWeapon",
description = "When a player picks up a weapon.",
parameters = {
{
name = "player",
description = "The player who picks up the weapon.",
type = "Player"
},
{
name = "entity",
description = "Entity of spawned weapon.",
type = "Entity"
},
{
name = "weapon",
description = "The weapon entity that the player is holding after picking up the weapon.",
type = "Weapon"
}
},
returns = {
},
}

View File

@@ -0,0 +1,11 @@
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Spawned Weapon"
ENT.Author = "Rickster"
ENT.Spawnable = false
ENT.IsSpawnedWeapon = true
function ENT:SetupDataTables()
self:NetworkVar("Int", 0, "amount")
self:NetworkVar("String", 0, "WeaponClass")
end

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