Initial commit

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

View File

@@ -0,0 +1,165 @@
local meta = FindMetaTable("Entity")
local black = color_black
local white = Color(255, 255, 255, 200)
local red = Color(128, 30, 30, 255)
local changeDoorAccess = false
local function updatePrivs()
CAMI.PlayerHasAccess(LocalPlayer(), "DarkRP_ChangeDoorSettings", function(b, _)
changeDoorAccess = b
end)
end
-- Timer due to lack of "on privilege changed" hook
hook.Add("InitPostEntity", "Load door privileges", function()
updatePrivs()
timer.Create("Door changeDoorAccess checker", 1, 0, updatePrivs)
end)
function meta:drawOwnableInfo()
local ply = LocalPlayer()
if ply:InVehicle() and not ply:GetAllowWeaponsInVehicle() then return end
-- Look, if you want to change the way door ownership is drawn, don't edit this file, use the hook instead!
local doorDrawing = hook.Call("HUDDrawDoorData", nil, self)
if doorDrawing == true then return end
local blocked = self:getKeysNonOwnable()
local doorTeams = self:getKeysDoorTeams()
local doorGroup = self:getKeysDoorGroup()
local playerOwned = self:isKeysOwned() or table.GetFirstValue(self:getKeysCoOwners() or {}) ~= nil
local owned = playerOwned or doorGroup or doorTeams
local doorInfo = {}
local title = self:getKeysTitle()
if title then table.insert(doorInfo, title) end
if owned then
table.insert(doorInfo, DarkRP.getPhrase("keys_owned_by"))
end
if playerOwned then
if self:isKeysOwned() then table.insert(doorInfo, self:getDoorOwner():Nick()) end
for k in pairs(self:getKeysCoOwners() or {}) do
local ent = Player(k)
if not IsValid(ent) or not ent:IsPlayer() then continue end
table.insert(doorInfo, ent:Nick())
end
local allowedCoOwn = self:getKeysAllowedToOwn()
if allowedCoOwn and not fn.Null(allowedCoOwn) then
table.insert(doorInfo, DarkRP.getPhrase("keys_other_allowed"))
for k in pairs(allowedCoOwn) do
local ent = Player(k)
if not IsValid(ent) or not ent:IsPlayer() then continue end
table.insert(doorInfo, ent:Nick())
end
end
elseif doorGroup then
table.insert(doorInfo, doorGroup)
elseif doorTeams then
for k, v in pairs(doorTeams) do
if not v or not RPExtraTeams[k] then continue end
table.insert(doorInfo, RPExtraTeams[k].name)
end
elseif blocked and changeDoorAccess then
table.insert(doorInfo, DarkRP.getPhrase("keys_allow_ownership"))
elseif not blocked then
table.insert(doorInfo, DarkRP.getPhrase("keys_unowned"))
if changeDoorAccess then
table.insert(doorInfo, DarkRP.getPhrase("keys_disallow_ownership"))
end
end
if self:IsVehicle() then
local driver = self:GetDriver()
if driver:IsPlayer() then
table.insert(doorInfo, DarkRP.getPhrase("driver", driver:Nick()))
end
end
local x, y = ScrW() / 2, ScrH() / 2
local text = table.concat(doorInfo, "\n")
draw.DrawNonParsedText(text, "Roboto20", x , y + 1 , black, 1)
draw.DrawNonParsedText(text, "Roboto20", x, y, (blocked or owned) and white or red, 1)
end
--[[---------------------------------------------------------------------------
Door data
---------------------------------------------------------------------------]]
DarkRP.doorData = DarkRP.doorData or {}
--[[---------------------------------------------------------------------------
Interface functions
---------------------------------------------------------------------------]]
function meta:getDoorData()
local doorData = DarkRP.doorData[self:EntIndex()] or {}
self.DoorData = doorData -- Backwards compatibility
return doorData
end
--[[---------------------------------------------------------------------------
Networking
---------------------------------------------------------------------------]]
--[[---------------------------------------------------------------------------
Retrieve all the data for all doors
---------------------------------------------------------------------------]]
local function retrieveAllDoorData(len)
local count = net.ReadUInt(16)
for i = 1, count do
local ix = net.ReadUInt(16)
local varCount = net.ReadUInt(8)
DarkRP.doorData[ix] = DarkRP.doorData[ix] or {}
for vc = 1, varCount do
local name, value = DarkRP.readNetDoorVar()
DarkRP.doorData[ix][name] = value
end
end
end
net.Receive("DarkRP_AllDoorData", retrieveAllDoorData)
--[[---------------------------------------------------------------------------
Update changed variables
---------------------------------------------------------------------------]]
local function updateDoorData()
local door = net.ReadUInt(32)
DarkRP.doorData[door] = DarkRP.doorData[door] or {}
local var, value = DarkRP.readNetDoorVar()
DarkRP.doorData[door][var] = value
end
net.Receive("DarkRP_UpdateDoorData", updateDoorData)
--[[---------------------------------------------------------------------------
Set a value of a single doorvar to nil
---------------------------------------------------------------------------]]
local function removeDoorVar()
local door = net.ReadUInt(16)
local id = net.ReadUInt(8)
local name = id == 0 and net.ReadString() or DarkRP.getDoorVars()[id].name
if not DarkRP.doorData[door] then return end
DarkRP.doorData[door][name] = nil
end
net.Receive("DarkRP_RemoveDoorVar", removeDoorVar)
--[[---------------------------------------------------------------------------
Remove doordata of removed entity
---------------------------------------------------------------------------]]
local function removeDoorData()
local door = net.ReadUInt(32)
DarkRP.doorData[door] = nil
end
net.Receive("DarkRP_RemoveDoorData", removeDoorData)

View File

@@ -0,0 +1,48 @@
DarkRP.readNetDoorVar = DarkRP.stub{
name = "readNetDoorVar",
description = "Internal function. You probably shouldn't need this. DarkRP calls this function when reading DoorVar net messages. This function reads the net data for a specific DoorVar.",
parameters = {
},
returns = {
{
name = "name",
description = "The name of the DoorVar.",
type = "string"
},
{
name = "value",
description = "The value of the DoorVar.",
type = "any"
}
},
metatable = DarkRP
}
DarkRP.ENTITY.drawOwnableInfo = DarkRP.stub{
name = "drawOwnableInfo",
description = "Draw the ownability information on a door or vehicle.",
parameters = {
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.hookStub{
name = "HUDDrawDoorData",
description = "Called when DarkRP is about to draw the door ownability information of a door or vehicle. Override this hook to ",
parameters = {
{
name = "ent",
description = "The door or vehicle of which the ownability information is about to be drawn.",
type = "Entity"
}
},
returns = {
{
name = "override",
description = "Return true in your hook to disable the default drawing and use your own.",
type = "boolean"
}
}
}

View File

@@ -0,0 +1,323 @@
local meta = FindMetaTable("Entity")
local plyMeta = FindMetaTable("Player")
local ownableDoors = {
["func_door"] = true,
["func_door_rotating"] = true,
["prop_door_rotating"] = true
}
local unOwnableDoors = {
["func_door"] = true,
["func_door_rotating"] = true,
["prop_door_rotating"] = true,
["func_movelinear"] = true,
["prop_dynamic"] = true
}
function meta:isKeysOwnable()
if not IsValid(self) then return false end
local class = self:GetClass()
if (ownableDoors[class] or
(GAMEMODE.Config.allowvehicleowning and self:IsVehicle() and (not IsValid(self:GetParent()) or not self:GetParent():IsVehicle()))) then
return true
end
return false
end
function meta:isDoor()
local class = self:GetClass()
if unOwnableDoors[class] then
return true
end
return false
end
function meta:isKeysOwned()
if IsValid(self:getDoorOwner()) then return true end
return false
end
function meta:getDoorOwner()
local doorData = self:getDoorData()
if not doorData then return nil end
return doorData.owner and Player(doorData.owner) or nil
end
function meta:isMasterOwner(ply)
return ply == self:getDoorOwner()
end
function meta:isKeysOwnedBy(ply)
if self:isMasterOwner(ply) then return true end
local coOwners = self:getKeysCoOwners()
return coOwners and coOwners[ply:UserID()] or false
end
function meta:isKeysAllowedToOwn(ply)
local doorData = self:getDoorData()
if not doorData then return false end
return doorData.allowedToOwn and doorData.allowedToOwn[ply:UserID()] or false
end
function meta:getKeysNonOwnable()
local doorData = self:getDoorData()
if not doorData then return nil end
return doorData.nonOwnable
end
function meta:getKeysTitle()
local doorData = self:getDoorData()
if not doorData then return nil end
return doorData.title
end
function meta:getKeysDoorGroup()
local doorData = self:getDoorData()
if not doorData then return nil end
return doorData.groupOwn
end
function meta:getKeysDoorTeams()
local doorData = self:getDoorData()
if not doorData or table.IsEmpty(doorData.teamOwn or {}) then return nil end
return doorData.teamOwn
end
function meta:getKeysAllowedToOwn()
local doorData = self:getDoorData()
if not doorData then return nil end
return doorData.allowedToOwn
end
function meta:getKeysCoOwners()
local doorData = self:getDoorData()
if not doorData then return nil end
return doorData.extraOwners
end
local function canLockUnlock(ply, ent)
local Team = ply:Team()
local group = ent:getKeysDoorGroup()
local teamOwn = ent:getKeysDoorTeams()
return ent:isKeysOwnedBy(ply) or
(group and table.HasValue(RPExtraTeamDoors[group] or {}, Team)) or
(teamOwn and teamOwn[Team])
end
function plyMeta:canKeysLock(ent)
local canLock = hook.Run("canKeysLock", self, ent)
if canLock ~= nil then return canLock end
return canLockUnlock(self, ent)
end
function plyMeta:canKeysUnlock(ent)
local canUnlock = hook.Run("canKeysUnlock", self, ent)
if canUnlock ~= nil then return canUnlock end
return canLockUnlock(self, ent)
end
local netDoorVars = {}
local netDoorVarsByName = {}
DarkRP.getDoorVars = fp{fn.Id, netDoorVars}
DarkRP.getDoorVarsByName = fp{fn.Id, netDoorVarsByName}
function DarkRP.registerDoorVar(name, writeFn, readFn)
netDoorVarsByName[name] = {name = name, write = writeFn, read = readFn}
netDoorVarsByName[name].id = table.insert(netDoorVars, netDoorVarsByName[name])
end
if SERVER then
function DarkRP.writeNetDoorVar(name, value)
local var = netDoorVarsByName[name]
-- Not registered, send inefficiently
if not var then
net.WriteUInt(0, 8) -- indicate unregistered
net.WriteString(name)
net.WriteType(value)
return
end
net.WriteUInt(var.id, 8)
var.write(value)
end
end
if CLIENT then
function DarkRP.readNetDoorVar()
local id = net.ReadUInt(8)
-- unregistered var
if id == 0 then
return net.ReadString(), net.ReadType(net.ReadUInt(8))
end
if not netDoorVars[id] then
DarkRP.error("Unregistered DarkRP Doorvar clientside: " .. id, 2, {"Some addon is registering some DoorVar serverside, but not clientside."})
end
return netDoorVars[id].name, netDoorVars[id].read()
end
end
DarkRP.registerDoorVar("groupOwn",
function(val)
net.WriteUInt(RPExtraTeamDoorIDs[val], 16)
end,
function()
local id = net.ReadUInt(16)
for name, id2 in pairs(RPExtraTeamDoorIDs) do
if id == id2 then return name end
end
end
)
-- Net helper function for writing tables with numbers as keys and bools as values
local function writeNumBoolTbl(tbl)
net.WriteUInt(table.Count(tbl), 10)
for num, _ in pairs(tbl) do
net.WriteUInt(num, 16)
end
end
-- Net helper function for reading tables with numbers as keys and bools as values
local function readNumBoolTbl(tbl)
local res = {}
local count = net.ReadUInt(10)
for i = 1, count do
res[net.ReadUInt(16)] = true
end
return res
end
DarkRP.registerDoorVar("owner", fp{fn.Flip(net.WriteInt), 16}, fp{net.ReadUInt, 16})
DarkRP.registerDoorVar("nonOwnable", net.WriteBool, net.ReadBool)
DarkRP.registerDoorVar("teamOwn", writeNumBoolTbl, readNumBoolTbl)
DarkRP.registerDoorVar("allowedToOwn", writeNumBoolTbl, readNumBoolTbl)
DarkRP.registerDoorVar("extraOwners", writeNumBoolTbl, readNumBoolTbl)
DarkRP.registerDoorVar("title", net.WriteString, net.ReadString)
--[[---------------------------------------------------------------------------
Commands
---------------------------------------------------------------------------]]
DarkRP.declareChatCommand{
command = "toggleownable",
description = "Toggle ownability status on this door.",
delay = 1.5
}
DarkRP.declareChatCommand{
command = "togglegroupownable",
description = "Set this door group ownable.",
delay = 1.5
}
DarkRP.declareChatCommand{
command = "toggleteamownable",
description = "Toggle this door ownable by a given team.",
delay = 1.5
}
DarkRP.declareChatCommand{
command = "toggleown",
description = "Own or unown the door you're looking at.",
delay = 0.5
}
DarkRP.declareChatCommand{
command = "unownalldoors",
description = "Sell all of your doors.",
delay = 1.5
}
DarkRP.chatCommandAlias("unownalldoors", "sellalldoors")
DarkRP.declareChatCommand{
command = "title",
description = "Set the title of the door you're looking at.",
delay = 1.5
}
DarkRP.declareChatCommand{
command = "removeowner",
description = "Remove an owner from the door you're looking at.",
delay = 0.5
}
DarkRP.declareChatCommand{
command = "ro",
description = "Remove an owner from the door you're looking at.",
delay = 0.5
}
DarkRP.declareChatCommand{
command = "addowner",
description = "Invite someone to co-own the door you're looking at.",
delay = 0.5
}
DarkRP.declareChatCommand{
command = "ao",
description = "Invite someone to co-own the door you're looking at.",
delay = 0.5
}
DarkRP.declareChatCommand{
command = "forceunlock",
description = "Force the door you're looking at to be unlocked. This is saved.",
delay = 0.5
}
DarkRP.declareChatCommand{
command = "forceremoveowner",
description = "Forcefully remove an owner from the door you're looking at.",
delay = 0.5
}
DarkRP.declareChatCommand{
command = "forceunownall",
description = "Force a player to unown all the doors and vehicles they have.",
delay = 0.5,
tableArgs = true
}
DarkRP.declareChatCommand{
command = "forcelock",
description = "Force the door you're looking at to be locked. This is saved.",
delay = 0.5
}
DarkRP.declareChatCommand{
command = "forceunown",
description = "Forcefully remove any owners from the door you're looking at.",
delay = 0.5
}
DarkRP.declareChatCommand{
command = "forceown",
description = "Forcefully make someone own the door you're looking at.",
delay = 0.5
}

View File

@@ -0,0 +1,377 @@
DarkRP.ENTITY.getDoorData = DarkRP.stub{
name = "getDoorData",
description = "Internal function to get the door/vehicle data.",
parameters = {
},
returns = {
{
name = "doordata",
description = "All the DarkRP information on a door or vehicle.",
type = "table"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.isKeysOwnable = DarkRP.stub{
name = "isKeysOwnable",
description = "Whether this door can be bought.",
parameters = {
},
returns = {
{
name = "answer",
description = "Whether the door can be bought.",
type = "boolean"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.isDoor = DarkRP.stub{
name = "isDoor",
description = "Whether this entity is considered a door in DarkRP.",
parameters = {
},
returns = {
{
name = "answer",
description = "Whether it's a door.",
type = "boolean"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.isKeysOwned = DarkRP.stub{
name = "isKeysOwned",
description = "Whether this door is owned by someone.",
parameters = {
},
returns = {
{
name = "answer",
description = "Whether it's owned.",
type = "boolean"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.getDoorOwner = DarkRP.stub{
name = "getDoorOwner",
description = "Get the owner of a door.",
parameters = {
},
returns = {
{
name = "owner",
description = "The owner of the door.",
type = "Player"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.isMasterOwner = DarkRP.stub{
name = "isMasterOwner",
description = "Whether the player is the main owner of the door (as opposed to a co-owner).",
parameters = {
{
name = "ply",
description = "The player to query.",
type = "Player",
optional = false
}
},
returns = {
{
name = "answer",
description = "Whether this player is the master owner.",
type = "boolean"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.isKeysOwnedBy = DarkRP.stub{
name = "isKeysOwnedBy",
description = "Whether this door is owned or co-owned by this player",
parameters = {
{
name = "ply",
description = "The player to query.",
type = "Player",
optional = false
}
},
returns = {
{
name = "answer",
description = "Whether this door is (co-)owned by the player.",
type = "boolean"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.isKeysAllowedToOwn = DarkRP.stub{
name = "isKeysAllowedToOwn",
description = "Whether this player is allowed to co-own a door, as decided by the master door owner.",
parameters = {
{
name = "ply",
description = "The player to query.",
type = "Player",
optional = false
}
},
returns = {
{
name = "answer",
description = "Whether this door is (co-)ownable by the player.",
type = "boolean"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.getKeysNonOwnable = DarkRP.stub{
name = "getKeysNonOwnable",
description = "Whether ownability of this door/vehicle is disabled.",
parameters = {
},
returns = {
{
name = "title",
description = "The ownability status.",
type = "boolean"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.getKeysTitle = DarkRP.stub{
name = "getKeysTitle",
description = "Get the title of this door or vehicle.",
parameters = {
},
returns = {
{
name = "title",
description = "The title of the door or vehicle.",
type = "string"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.getKeysDoorGroup = DarkRP.stub{
name = "getKeysDoorGroup",
description = "The door group of a door if it exists.",
parameters = {
},
returns = {
{
name = "group",
description = "The door group.",
type = "string"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.getKeysDoorTeams = DarkRP.stub{
name = "getKeysDoorTeams",
description = "The teams that are allowed to open this door.",
parameters = {
},
returns = {
{
name = "teams",
description = "The door teams.",
type = "table"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.getKeysAllowedToOwn = DarkRP.stub{
name = "getKeysAllowedToOwn",
description = "The list of people of which the master door owner has added as allowed to own.",
parameters = {
},
returns = {
{
name = "players",
description = "The list of people allowed to own.",
type = "table"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.getKeysCoOwners = DarkRP.stub{
name = "getKeysCoOwners",
description = "The list of people who co-own the door.",
parameters = {
},
returns = {
{
name = "players",
description = "The list of people allowed to own. The keys of this table are UserIDs, the values are booleans.",
type = "table"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.PLAYER.canKeysLock = DarkRP.stub{
name = "canKeysLock",
description = "Whether the player can lock a given door.",
parameters = {
{
name = "door",
description = "The door",
optional = false,
type = "Entity"
}
},
returns = {
{
name = "allowed",
description = "Whether the player is allowed to lock the door.",
type = "boolean"
}
},
metatable = DarkRP.PLAYER
}
DarkRP.PLAYER.canKeysUnlock = DarkRP.stub{
name = "canKeysUnlock",
description = "Whether the player can unlock a given door.",
parameters = {
{
name = "door",
description = "The door",
optional = false,
type = "Entity"
}
},
returns = {
{
name = "allowed",
description = "Whether the player is allowed to unlock the door.",
type = "boolean"
}
},
metatable = DarkRP.PLAYER
}
DarkRP.registerDoorVar = DarkRP.stub{
name = "registerDoorVar",
description = "Register a door variable by name. You should definitely register door variables. Registering DarkRPVars will make networking much more efficient.",
parameters = {
{
name = "name",
description = "The name of the door var.",
type = "string",
optional = false
},
{
name = "writeFn",
description = "The function that writes a value for this door var. Examples: net.WriteString, function(val) net.WriteUInt(val, 8) end.",
type = "function",
optional = false
},
{
name = "readFn",
description = "The function that reads and returns a value for this door var. Examples: net.ReadString, function() return net.ReadUInt(8) end.",
type = "function",
optional = false
}
},
returns = {
},
metatable = DarkRP
}
DarkRP.getDoorVars = DarkRP.stub{
name = "getDoorVars",
description = "Internal function, retrieves all the registered door variables.",
parameters = {
},
returns = {
{
name = "doorvars",
description = "The door variables, indexed by number",
type = "table"
}
},
metatable = DarkRP
}
DarkRP.getDoorVarsByName = DarkRP.stub{
name = "getDoorVarsByName",
description = "Internal function, retrieves all the registered door variables, indeded by their names.",
parameters = {
},
returns = {
{
name = "doorvars",
description = "The door variables, indexed by name",
type = "table"
}
},
metatable = DarkRP
}
DarkRP.hookStub{
name = "canKeysLock",
description = "Whether the player can lock a given door. This hook is run when ply:canKeysLock is called.",
parameters = {
{
name = "ply",
description = "The player",
type = "Player"
},
{
name = "door",
description = "The door",
type = "Entity"
}
},
returns = {
{
name = "allowed",
description = "Whether the player is allowed to lock the door.",
type = "boolean"
}
}
}
DarkRP.hookStub{
name = "canKeysUnlock",
description = "Whether the player can unlock a given door. This hook is run when ply:canKeysUnlock is called.",
parameters = {
{
name = "ply",
description = "The player",
type = "Player"
},
{
name = "door",
description = "The door",
type = "Entity"
}
},
returns = {
{
name = "allowed",
description = "Whether the player is allowed to unlock the door.",
type = "boolean"
}
}
}

View File

@@ -0,0 +1,172 @@
local function ccDoorUnOwn(ply, args)
if ply:EntIndex() == 0 then
print(DarkRP.getPhrase("cmd_cant_be_run_server_console"))
return
end
local trace = ply:GetEyeTrace()
local ent = trace.Entity
if not IsValid(ent) or not ent:isKeysOwnable() or not ent:getDoorOwner() or ply:EyePos():DistToSqr(ent:GetPos()) > 40000 then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("must_be_looking_at", DarkRP.getPhrase("door_or_vehicle")))
return
end
ent:Fire("unlock", "", 0)
ent:keysUnOwn()
DarkRP.log(ply:Nick() .. " (" .. ply:SteamID() .. ") force-unowned a door with forceunown", Color(30, 30, 30))
DarkRP.notify(ply, 0, 4, "Forcefully unowned")
end
DarkRP.definePrivilegedChatCommand("forceunown", "DarkRP_SetDoorOwner", ccDoorUnOwn)
local function unownAll(ply, args)
local target = DarkRP.findPlayer(args[1])
if not IsValid(target) then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("could_not_find", args))
return
end
target:keysUnOwnAll()
if ply:EntIndex() == 0 then
DarkRP.log("Console force-unowned all doors owned by " .. target:Nick(), Color(30, 30, 30))
else
DarkRP.log(ply:Nick() .. " (" .. ply:SteamID() .. ") force-unowned all doors owned by " .. target:Nick(), Color(30, 30, 30))
end
DarkRP.notify(ply, 0, 4, "All doors of " .. target:Nick() .. " are now unowned")
end
DarkRP.definePrivilegedChatCommand("forceunownall", "DarkRP_SetDoorOwner", unownAll)
local function ccAddOwner(ply, args)
if ply:EntIndex() == 0 then
print(DarkRP.getPhrase("cmd_cant_be_run_server_console"))
return
end
local trace = ply:GetEyeTrace()
local ent = trace.Entity
if not IsValid(ent) or not ent:isKeysOwnable() or ent:getKeysNonOwnable() or ent:getKeysDoorGroup() or ent:getKeysDoorTeams() or ply:EyePos():DistToSqr(ent:GetPos()) > 40000 then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("must_be_looking_at", DarkRP.getPhrase("door_or_vehicle")))
return
end
local target = DarkRP.findPlayer(args)
if not target then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("could_not_find", args))
return
end
if ent:isKeysOwned() then
if not ent:isKeysOwnedBy(target) and not ent:isKeysAllowedToOwn(target) then
ent:addKeysAllowedToOwn(target)
else
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("rp_addowner_already_owns_door", target))
end
return
end
ent:keysOwn(target)
DarkRP.log(ply:Nick() .. " (" .. ply:SteamID() .. ") force-added a door owner with forceown", Color(30, 30, 30))
DarkRP.notify(ply, 0, 4, "Forcefully added " .. target:Nick())
end
DarkRP.definePrivilegedChatCommand("forceown", "DarkRP_SetDoorOwner", ccAddOwner)
local function ccRemoveOwner(ply, args)
if ply:EntIndex() == 0 then
print(DarkRP.getPhrase("cmd_cant_be_run_server_console"))
return
end
local trace = ply:GetEyeTrace()
local ent = trace.Entity
if not IsValid(ent) or not ent:isKeysOwnable() or ent:getKeysNonOwnable() or ent:getKeysDoorGroup() or ent:getKeysDoorTeams() or ply:EyePos():DistToSqr(ent:GetPos()) > 40000 then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("must_be_looking_at", DarkRP.getPhrase("door_or_vehicle")))
return
end
local target = DarkRP.findPlayer(args)
if not target then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("could_not_find", args))
return
end
if ent:isKeysAllowedToOwn(target) then
ent:removeKeysAllowedToOwn(target)
end
if ent:isMasterOwner(target) then
ent:keysUnOwn()
elseif ent:isKeysOwnedBy(target) then
ent:removeKeysDoorOwner(target)
end
DarkRP.log(ply:Nick() .. " (" .. ply:SteamID() .. ") force-removed a door owner with forceremoveowner", Color(30, 30, 30))
DarkRP.notify(ply, 0, 4, "Forcefully removed " .. target:Nick())
end
DarkRP.definePrivilegedChatCommand("forceremoveowner", "DarkRP_SetDoorOwner", ccRemoveOwner)
local function ccLock(ply, args)
if ply:EntIndex() == 0 then
print(DarkRP.getPhrase("cmd_cant_be_run_server_console"))
return
end
local trace = ply:GetEyeTrace()
local ent = trace.Entity
if not IsValid(ent) or not ent:isKeysOwnable() or ply:EyePos():DistToSqr(ent:GetPos()) > 40000 then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("must_be_looking_at", DarkRP.getPhrase("door_or_vehicle")))
return
end
DarkRP.notify(ply, 0, 4, DarkRP.getPhrase("locked"))
ent:keysLock()
if not ent:CreatedByMap() then return end
MySQLite.query(string.format([[REPLACE INTO darkrp_door VALUES(%s, %s, %s, 1, %s);]],
MySQLite.SQLStr(ent:doorIndex()),
MySQLite.SQLStr(string.lower(game.GetMap())),
MySQLite.SQLStr(ent:getKeysTitle() or ""),
ent:getKeysNonOwnable() and 1 or 0
))
DarkRP.log(ply:Nick() .. " (" .. ply:SteamID() .. ") force-locked a door with forcelock (locked door is saved)", Color(30, 30, 30))
DarkRP.notify(ply, 0, 4, "Forcefully locked")
end
DarkRP.definePrivilegedChatCommand("forcelock", "DarkRP_ChangeDoorSettings", ccLock)
local function ccUnLock(ply, args)
if ply:EntIndex() == 0 then
print(DarkRP.getPhrase("cmd_cant_be_run_server_console"))
return
end
local trace = ply:GetEyeTrace()
local ent = trace.Entity
if not IsValid(ent) or not ent:isKeysOwnable() or ply:EyePos():DistToSqr(ent:GetPos()) > 40000 then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("must_be_looking_at", DarkRP.getPhrase("door_or_vehicle")))
return
end
DarkRP.notify(ply, 0, 4, DarkRP.getPhrase("unlocked"))
ent:keysUnLock()
if not ent:CreatedByMap() then return end
MySQLite.query(string.format([[REPLACE INTO darkrp_door VALUES(%s, %s, %s, 0, %s);]],
MySQLite.SQLStr(ent:doorIndex()),
MySQLite.SQLStr(string.lower(game.GetMap())),
MySQLite.SQLStr(ent:getKeysTitle() or ""),
ent:getKeysNonOwnable() and 1 or 0
))
DarkRP.log(ply:Nick() .. " (" .. ply:SteamID() .. ") force-unlocked a door with forcelock (unlocked door is saved)", Color(30, 30, 30))
DarkRP.notify(ply, 0, 4, "Forcefully unlocked")
end
DarkRP.definePrivilegedChatCommand("forceunlock", "DarkRP_ChangeDoorSettings", ccUnLock)

View File

@@ -0,0 +1,592 @@
local meta = FindMetaTable("Entity")
local pmeta = FindMetaTable("Player")
--[[---------------------------------------------------------------------------
Functions
---------------------------------------------------------------------------]]
function meta:doorIndex()
return self:CreatedByMap() and self:MapCreationID() or nil
end
function DarkRP.doorToEntIndex(num)
local ent = ents.GetMapCreatedEntity(num)
return IsValid(ent) and ent:EntIndex() or nil
end
function DarkRP.doorIndexToEnt(num)
return ents.GetMapCreatedEntity(num) or NULL
end
function meta:isLocked()
local save = self:GetSaveTable()
return save and ((self:isDoor() and save.m_bLocked) or (self:IsVehicle() and save.VehicleLocked))
end
function meta:keysLock()
self:Fire("lock", "", 0)
if isfunction(self.Lock) then self:Lock(true) end -- SCars
if IsValid(self.EntOwner) and self.EntOwner ~= self then return self.EntOwner:keysLock() end -- SCars
hook.Call("onKeysLocked", nil, self)
end
function meta:keysUnLock()
self:Fire("unlock", "", 0)
if isfunction(self.UnLock) then self:UnLock(true) end -- SCars
if IsValid(self.EntOwner) and self.EntOwner ~= self then return self.EntOwner:keysUnLock() end -- SCars
hook.Call("onKeysUnlocked", nil, self)
end
function meta:keysOwn(ply)
if self:isKeysAllowedToOwn(ply) then
self:addKeysDoorOwner(ply)
return
end
local Owner = self:CPPIGetOwner()
-- Increase vehicle count
if self:IsVehicle() then
if IsValid(ply) then
ply.Vehicles = ply.Vehicles or 0
ply.Vehicles = ply.Vehicles + 1
self.SID = ply.SID
end
-- Decrease vehicle count of the original owner
if IsValid(Owner) and Owner ~= ply then
Owner.Vehicles = Owner.Vehicles or 1
Owner.Vehicles = Owner.Vehicles - 1
end
end
if self:IsVehicle() then
self:CPPISetOwner(ply)
end
if not self:isKeysOwned() and not self:isKeysOwnedBy(ply) then
local doorData = self:getDoorData()
doorData.owner = ply:UserID()
DarkRP.updateDoorData(self, "owner")
end
ply.OwnedNumz = ply.OwnedNumz or 0
if ply.OwnedNumz == 0 and GAMEMODE.Config.propertytax then
timer.Create(ply:SteamID64() .. "propertytax", 270, 0, function() ply.doPropertyTax(ply) end)
end
ply.OwnedNumz = ply.OwnedNumz + 1
ply.Ownedz[self:EntIndex()] = self
end
function meta:keysUnOwn(ply)
if not ply then
ply = self:getDoorOwner()
if not IsValid(ply) then return end
end
if self:isMasterOwner(ply) then
local doorData = self:getDoorData()
self:removeAllKeysExtraOwners()
self:setKeysTitle(nil)
doorData.owner = nil
DarkRP.updateDoorData(self, "owner")
else
self:removeKeysDoorOwner(ply)
end
ply.Ownedz[self:EntIndex()] = nil
ply.OwnedNumz = math.Clamp((ply.OwnedNumz or 1) - 1, 0, math.huge)
end
function pmeta:keysUnOwnAll()
for entIndex, ent in pairs(self.Ownedz or {}) do
if not IsValid(ent) or not ent:isKeysOwnable() then self.Ownedz[entIndex] = nil continue end
if ent:isMasterOwner(self) then
ent:Fire("unlock", "", 0.6)
end
ent:keysUnOwn(self)
end
for _, ply in ipairs(player.GetAll()) do
if ply == self then continue end
for _, ent in pairs(ply.Ownedz or {}) do
if IsValid(ent) and ent:isKeysAllowedToOwn(self) then
ent:removeKeysAllowedToOwn(self)
end
end
end
self.OwnedNumz = 0
end
local function taxesUnOwnAll(ply, taxables)
for _, ent in ipairs(taxables) do
if ent:isMasterOwner(ply) then
ent:Fire("unlock", "", 0.6)
end
ent:keysUnOwn(ply)
end
end
function pmeta:doPropertyTax()
if not GAMEMODE.Config.propertytax then return end
if self:isCP() and GAMEMODE.Config.cit_propertytax then return end
local taxables = {}
for entIndex, ent in pairs(self.Ownedz or {}) do
if not IsValid(ent) or not ent:isKeysOwnable() then self.Ownedz[entIndex] = nil continue end
local isAllowed = hook.Call("canTaxEntity", nil, self, ent)
if isAllowed == false then continue end
table.insert(taxables, ent)
end
-- co-owned doors
for _, ply in ipairs(player.GetAll()) do
if ply == self then continue end
for _, ent in pairs(ply.Ownedz or {}) do
if not IsValid(ent) or not ent:isKeysOwnedBy(self) then continue end
local isAllowed = hook.Call("canTaxEntity", nil, self, ent)
if isAllowed == false then continue end
table.insert(taxables, ent)
end
end
local numowned = #taxables
if numowned <= 0 then return end
local price = 10
local tax = price * numowned + math.random(-5, 5)
local shouldTax, taxOverride = hook.Call("canPropertyTax", nil, self, tax)
if shouldTax == false then return end
tax = taxOverride or tax
if tax == 0 then return end
local canAfford = self:canAfford(tax)
if canAfford then
self:addMoney(-tax)
DarkRP.notify(self, 0, 5, DarkRP.getPhrase("property_tax", DarkRP.formatMoney(tax)))
else
taxesUnOwnAll(self, taxables)
DarkRP.notify(self, 1, 8, DarkRP.getPhrase("property_tax_cant_afford"))
end
hook.Call("onPropertyTax", nil, self, tax, canAfford)
end
function pmeta:initiateTax()
local taxtime = GAMEMODE.Config.wallettaxtime
local uid = self:SteamID64() -- so we can destroy the timer if the player leaves
timer.Create("rp_tax_" .. uid, taxtime or 600, 0, function()
if not IsValid(self) then
timer.Remove("rp_tax_" .. uid)
return
end
if not GAMEMODE.Config.wallettax then
return -- Don't remove the hook in case it's turned on afterwards.
end
local money = self:getDarkRPVar("money")
local mintax = GAMEMODE.Config.wallettaxmin / 100
local maxtax = GAMEMODE.Config.wallettaxmax / 100 -- convert to decimals for percentage calculations
local startMoney = GAMEMODE.Config.startingmoney
-- Variate the taxes between twice the starting money ($1000 by default) and 200 - 2 times the starting money (100.000 by default)
local tax = (money - (startMoney * 2)) / (startMoney * 198)
tax = math.Min(maxtax, mintax + (maxtax - mintax) * tax)
local taxAmount = tax * money
local shouldTax, amount = hook.Call("canTax", GAMEMODE, self, taxAmount)
if shouldTax == false then return end
taxAmount = amount or taxAmount
taxAmount = math.Max(0, taxAmount)
self:addMoney(-taxAmount)
DarkRP.notify(self, 3, 7, DarkRP.getPhrase("taxday", math.Round(taxAmount / money * 100, 3)))
hook.Call("onPaidTax", DarkRP.hooks, self, tax, money)
end)
end
function GM:canTax(ply)
-- Don't tax players if they have less than twice the starting amount
if ply:getDarkRPVar("money") < (GAMEMODE.Config.startingmoney * 2) then return false end
end
--[[---------------------------------------------------------------------------
Commands
---------------------------------------------------------------------------]]
local function SetDoorOwnable(ply)
local trace = ply:GetEyeTrace()
local ent = trace.Entity
if not IsValid(ent) or (not ent:isDoor() and not ent:IsVehicle()) or ply:GetPos():DistToSqr(ent:GetPos()) > 40000 then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("must_be_looking_at", DarkRP.getPhrase("door_or_vehicle")))
return
end
if IsValid(ent:getDoorOwner()) then
ent:keysUnOwn(ent:getDoorOwner())
end
ent:setKeysNonOwnable(not ent:getKeysNonOwnable())
ent:removeAllKeysExtraOwners()
ent:removeAllKeysAllowedToOwn()
ent:removeAllKeysDoorTeams()
ent:setDoorGroup(nil)
ent:setKeysTitle(nil)
-- Save it for future map loads
DarkRP.storeDoorData(ent)
DarkRP.storeDoorGroup(ent, nil)
DarkRP.storeTeamDoorOwnability(ent)
return ""
end
DarkRP.definePrivilegedChatCommand("toggleownable", "DarkRP_ChangeDoorSettings", SetDoorOwnable)
local function SetDoorGroupOwnable(ply, arg)
local trace = ply:GetEyeTrace()
local ent = trace.Entity
if not IsValid(ent) or (not ent:isDoor() and not ent:IsVehicle()) or ply:GetPos():DistToSqr(ent:GetPos()) > 40000 then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("must_be_looking_at", DarkRP.getPhrase("door_or_vehicle")))
return
end
if not RPExtraTeamDoors[arg] and arg ~= "" then DarkRP.notify(ply, 1, 10, DarkRP.getPhrase("door_group_doesnt_exist")) return "" end
ent:keysUnOwn()
ent:removeAllKeysDoorTeams()
local group = arg ~= "" and arg or nil
ent:setDoorGroup(group)
-- Save it for future map loads
DarkRP.storeDoorGroup(ent, group)
DarkRP.storeTeamDoorOwnability(ent)
DarkRP.notify(ply, 0, 8, DarkRP.getPhrase("door_group_set"))
return ""
end
DarkRP.definePrivilegedChatCommand("togglegroupownable", "DarkRP_ChangeDoorSettings", SetDoorGroupOwnable)
local function SetDoorTeamOwnable(ply, arg)
local trace = ply:GetEyeTrace()
local ent = trace.Entity
if not IsValid(ent) or (not ent:isDoor() and not ent:IsVehicle()) or ply:GetPos():DistToSqr(ent:GetPos()) > 40000 then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("must_be_looking_at", DarkRP.getPhrase("door_or_vehicle")))
return ""
end
arg = tonumber(arg)
if not arg then DarkRP.notify(ply, 1, 10, DarkRP.getPhrase("job_doesnt_exist")) return "" end
if not RPExtraTeams[arg] and arg ~= nil then DarkRP.notify(ply, 1, 10, DarkRP.getPhrase("job_doesnt_exist")) return "" end
if IsValid(ent:getDoorOwner()) then
ent:keysUnOwn(ent:getDoorOwner())
end
ent:setDoorGroup(nil)
DarkRP.storeDoorGroup(ent, nil)
local doorTeams = ent:getKeysDoorTeams()
if not doorTeams or not doorTeams[arg] then
ent:addKeysDoorTeam(arg)
else
ent:removeKeysDoorTeam(arg)
end
DarkRP.notify(ply, 0, 8, DarkRP.getPhrase("door_group_set"))
DarkRP.storeTeamDoorOwnability(ent)
ent:keysUnOwn()
return ""
end
DarkRP.definePrivilegedChatCommand("toggleteamownable", "DarkRP_ChangeDoorSettings", SetDoorTeamOwnable)
local function OwnDoor(ply)
local trace = ply:GetEyeTrace()
local ent = trace.Entity
if not IsValid(ent) or not ent:isKeysOwnable() or ply:GetPos():DistToSqr(ent:GetPos()) >= 40000 then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("must_be_looking_at", DarkRP.getPhrase("door_or_vehicle")))
return ""
end
local Owner = ent:CPPIGetOwner()
if ply:isArrested() then
DarkRP.notify(ply, 1, 5, DarkRP.getPhrase("door_unown_arrested"))
return ""
end
if ent:getKeysNonOwnable() or ent:getKeysDoorGroup() or not fn.Null(ent:getKeysDoorTeams() or {}) then
DarkRP.notify(ply, 1, 5, DarkRP.getPhrase("door_unownable"))
return ""
end
if ent:isKeysOwnedBy(ply) then
local bAllowed, strReason = hook.Call("playerSell" .. (ent:IsVehicle() and "Vehicle" or "Door"), GAMEMODE, ply, ent)
if bAllowed == false then
if strReason and strReason ~= "" then
DarkRP.notify(ply, 1, 4, strReason)
end
return ""
end
if ent:isMasterOwner(ply) then
ent:removeAllKeysExtraOwners()
ent:removeAllKeysAllowedToOwn()
ent:Fire("unlock", "", 0)
end
ent:keysUnOwn(ply)
ent:setKeysTitle(nil)
local GiveMoneyBack = math.floor((hook.Call("get" .. (ent:IsVehicle() and "Vehicle" or "Door") .. "Cost", GAMEMODE, ply, ent) * 0.666) + 0.5)
hook.Call("playerKeysSold", GAMEMODE, ply, ent, GiveMoneyBack)
ply:addMoney(GiveMoneyBack)
local bSuppress = hook.Call("hideSellDoorMessage", GAMEMODE, ply, ent)
if not bSuppress then
DarkRP.notify(ply, 0, 4, DarkRP.getPhrase("door_sold", DarkRP.formatMoney(GiveMoneyBack)))
end
else
if ent:isKeysOwned() and not ent:isKeysAllowedToOwn(ply) then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("door_already_owned"))
return ""
end
local iCost = hook.Call("get" .. (ent:IsVehicle() and "Vehicle" or "Door") .. "Cost", GAMEMODE, ply, ent)
if not ply:canAfford(iCost) then
DarkRP.notify(ply, 1, 4, ent:IsVehicle() and DarkRP.getPhrase("vehicle_cannot_afford") or DarkRP.getPhrase("door_cannot_afford"))
return ""
end
local bAllowed, strReason, bSuppress = hook.Call("playerBuy" .. (ent:IsVehicle() and "Vehicle" or "Door"), GAMEMODE, ply, ent)
if bAllowed == false then
if strReason and strReason ~= "" then
DarkRP.notify(ply, 1, 4, strReason)
end
return ""
end
local bVehicle = ent:IsVehicle()
if bVehicle and (ply.Vehicles or 0) >= GAMEMODE.Config.maxvehicles and Owner ~= ply then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("limit", DarkRP.getPhrase("vehicle")))
return ""
end
if not bVehicle and (ply.OwnedNumz or 0) >= GAMEMODE.Config.maxdoors then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("limit", DarkRP.getPhrase("door")))
return ""
end
ply:addMoney(-iCost)
if not bSuppress then
DarkRP.notify(ply, 0, 4, bVehicle and DarkRP.getPhrase("vehicle_bought", DarkRP.formatMoney(iCost), "") or DarkRP.getPhrase("door_bought", DarkRP.formatMoney(iCost), ""))
end
ent:keysOwn(ply)
hook.Call("playerBought" .. (bVehicle and "Vehicle" or "Door"), GAMEMODE, ply, ent, iCost)
end
return ""
end
DarkRP.defineChatCommand("toggleown", OwnDoor)
local function UnOwnAll(ply, cmd, args)
local amount = 0
local cost = 0
local unownables = {}
for entIndex, ent in pairs(ply.Ownedz or {}) do
if not IsValid(ent) or not ent:isKeysOwnable() then ply.Ownedz[entIndex] = nil continue end
table.insert(unownables, ent)
end
for _, otherPly in ipairs(player.GetAll()) do
if ply == otherPly then continue end
for _, ent in pairs(otherPly.Ownedz or {}) do
if IsValid(ent) and ent:isKeysOwnedBy(ply) then
table.insert(unownables, ent)
end
end
end
for entIndex, ent in ipairs(unownables) do
local bAllowed, _strReason = hook.Call("playerSell" .. (ent:IsVehicle() and "Vehicle" or "Door"), GAMEMODE, ply, ent)
if bAllowed == false then continue end
if ent:isMasterOwner(ply) then
ent:Fire("unlock", "", 0)
end
ent:keysUnOwn(ply)
amount = amount + 1
local GiveMoneyBack = math.floor((hook.Call("get" .. (ent:IsVehicle() and "Vehicle" or "Door") .. "Cost", GAMEMODE, ply, ent) * 0.666) + 0.5)
hook.Call("playerKeysSold", GAMEMODE, ply, ent, GiveMoneyBack)
cost = cost + GiveMoneyBack
end
if amount == 0 then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("no_doors_owned")) return "" end
ply:addMoney(math.floor(cost))
DarkRP.notify(ply, 2, 4, DarkRP.getPhrase("sold_x_doors", amount, DarkRP.formatMoney(math.floor(cost))))
return ""
end
DarkRP.defineChatCommand("unownalldoors", UnOwnAll)
local function SetDoorTitle(ply, args)
local trace = ply:GetEyeTrace()
local ent = trace.Entity
if not IsValid(ent) or not ent:isKeysOwnable() or ply:GetPos():DistToSqr(ent:GetPos()) >= 12100 then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("must_be_looking_at", DarkRP.getPhrase("door_or_vehicle")))
return ""
end
if ent:isKeysOwnedBy(ply) then
ent:setKeysTitle(args)
return ""
end
local function onCAMIResult(allowed)
if not allowed then
DarkRP.notify(ply, 1, 6, DarkRP.getPhrase("no_privilege"))
return
end
local hasTeams = not fn.Null(ent:getKeysDoorTeams() or {})
if ent:isKeysOwned() or ent:getKeysNonOwnable() or ent:getKeysDoorGroup() or hasTeams then
ent:setKeysTitle(args)
end
if ent:getKeysNonOwnable() or ent:getKeysDoorGroup() or hasTeams then
DarkRP.storeDoorData(trace.Entity)
end
end
CAMI.PlayerHasAccess(ply, "DarkRP_ChangeDoorSettings", onCAMIResult)
return ""
end
DarkRP.defineChatCommand("title", SetDoorTitle)
local function RemoveDoorOwner(ply, args)
local trace = ply:GetEyeTrace()
local ent = trace.Entity
if not IsValid(ent) or not ent:isKeysOwnable() or ply:GetPos():DistToSqr(ent:GetPos()) >= 12100 then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("must_be_looking_at", DarkRP.getPhrase("door_or_vehicle")))
return ""
end
local target = DarkRP.findPlayer(args)
if ent:getKeysNonOwnable() then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("door_rem_owners_unownable"))
return ""
end
if not target then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("could_not_find", tostring(args)))
return ""
end
if not ent:isKeysOwnedBy(ply) then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("do_not_own_ent"))
return ""
end
local canDo = hook.Call("onAllowedToOwnRemoved", nil, ply, ent, target)
if canDo == false then return "" end
if ent:isKeysAllowedToOwn(target) then
ent:removeKeysAllowedToOwn(target)
end
if ent:isKeysOwnedBy(target) then
ent:removeKeysDoorOwner(target)
end
return ""
end
DarkRP.defineChatCommand("removeowner", RemoveDoorOwner)
DarkRP.defineChatCommand("ro", RemoveDoorOwner)
local function AddDoorOwner(ply, args)
local trace = ply:GetEyeTrace()
local ent = trace.Entity
if not IsValid(ent) or not ent:isKeysOwnable() or ply:GetPos():DistToSqr(ent:GetPos()) >= 12100 then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("must_be_looking_at", DarkRP.getPhrase("door_or_vehicle")))
return ""
end
local target = DarkRP.findPlayer(args)
if ent:getKeysNonOwnable() then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("door_add_owners_unownable"))
return ""
end
if not target then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("could_not_find", tostring(args)))
return ""
end
if not ent:isKeysOwnedBy(ply) then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("do_not_own_ent"))
return ""
end
if ent:isKeysOwnedBy(target) or ent:isKeysAllowedToOwn(target) then
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("rp_addowner_already_owns_door", target:Nick()))
return ""
end
local canDo = hook.Call("onAllowedToOwnAdded", nil, ply, ent, target)
if canDo == false then return "" end
ent:addKeysAllowedToOwn(target)
return ""
end
DarkRP.defineChatCommand("addowner", AddDoorOwner)
DarkRP.defineChatCommand("ao", AddDoorOwner)

View File

@@ -0,0 +1,179 @@
util.AddNetworkString("DarkRP_UpdateDoorData")
util.AddNetworkString("DarkRP_RemoveDoorData")
util.AddNetworkString("DarkRP_RemoveDoorVar")
util.AddNetworkString("DarkRP_AllDoorData")
--[[---------------------------------------------------------------------------
Interface functions
---------------------------------------------------------------------------]]
local eMeta = FindMetaTable("Entity")
function eMeta:getDoorData()
if not self:isKeysOwnable() then return {} end
self.DoorData = self.DoorData or {}
return self.DoorData
end
function eMeta:setKeysNonOwnable(ownable)
self:getDoorData().nonOwnable = ownable or nil
DarkRP.updateDoorData(self, "nonOwnable")
end
function eMeta:setKeysTitle(title)
self:getDoorData().title = title ~= "" and title or nil
DarkRP.updateDoorData(self, "title")
end
function eMeta:setDoorGroup(group)
self:getDoorData().groupOwn = group
DarkRP.updateDoorData(self, "groupOwn")
end
function eMeta:addKeysDoorTeam(t)
local doorData = self:getDoorData()
doorData.teamOwn = doorData.teamOwn or {}
doorData.teamOwn[t] = true
DarkRP.updateDoorData(self, "teamOwn")
end
function eMeta:removeKeysDoorTeam(t)
local doorData = self:getDoorData()
doorData.teamOwn = doorData.teamOwn or {}
doorData.teamOwn[t] = nil
if fn.Null(doorData.teamOwn) then
doorData.teamOwn = nil
end
DarkRP.updateDoorData(self, "teamOwn")
end
function eMeta:removeAllKeysDoorTeams()
local doorData = self:getDoorData()
doorData.teamOwn = nil
DarkRP.updateDoorData(self, "teamOwn")
end
function eMeta:addKeysAllowedToOwn(ply)
local doorData = self:getDoorData()
doorData.allowedToOwn = doorData.allowedToOwn or {}
doorData.allowedToOwn[ply:UserID()] = true
DarkRP.updateDoorData(self, "allowedToOwn")
end
function eMeta:removeKeysAllowedToOwn(ply)
local doorData = self:getDoorData()
doorData.allowedToOwn = doorData.allowedToOwn or {}
doorData.allowedToOwn[ply:UserID()] = nil
if fn.Null(doorData.allowedToOwn) then
doorData.allowedToOwn = nil
end
DarkRP.updateDoorData(self, "allowedToOwn")
end
function eMeta:removeAllKeysAllowedToOwn()
local doorData = self:getDoorData()
doorData.allowedToOwn = nil
DarkRP.updateDoorData(self, "allowedToOwn")
end
function eMeta:addKeysDoorOwner(ply)
local doorData = self:getDoorData()
doorData.extraOwners = doorData.extraOwners or {}
doorData.extraOwners[ply:UserID()] = true
DarkRP.updateDoorData(self, "extraOwners")
self:removeKeysAllowedToOwn(ply)
end
function eMeta:removeKeysDoorOwner(ply)
local doorData = self:getDoorData()
doorData.extraOwners = doorData.extraOwners or {}
doorData.extraOwners[ply:UserID()] = nil
if fn.Null(doorData.extraOwners) then
doorData.extraOwners = nil
end
DarkRP.updateDoorData(self, "extraOwners")
end
function eMeta:removeAllKeysExtraOwners()
local doorData = self:getDoorData()
doorData.extraOwners = nil
DarkRP.updateDoorData(self, "extraOwners")
end
function eMeta:removeDoorData()
net.Start("DarkRP_RemoveDoorData")
net.WriteUInt(self:EntIndex(), 32)
net.Send(player.GetAll())
end
--[[---------------------------------------------------------------------------
Networking
---------------------------------------------------------------------------]]
local plyMeta = FindMetaTable("Player")
function plyMeta:sendDoorData()
if self:EntIndex() == 0 then return end
local res = {}
for _, v in ipairs(ents.GetAll()) do
if not v:getDoorData() or table.IsEmpty(v:getDoorData()) then continue end
res[v:EntIndex()] = v:getDoorData()
end
net.Start("DarkRP_AllDoorData")
net.WriteUInt(table.Count(res), 16)
for ix, vars in pairs(res) do
net.WriteUInt(ix, 16)
net.WriteUInt(table.Count(vars), 8)
for varName, value in pairs(vars) do
DarkRP.writeNetDoorVar(varName, value)
end
end
net.Send(self)
end
concommand.Add("_sendAllDoorData", fn.Id) -- Backwards compatibility
hook.Add("PlayerInitialSpawn", "DarkRP_DoorData", plyMeta.sendDoorData)
function DarkRP.updateDoorData(door, member)
if not IsValid(door) or not door:getDoorData() then error("Calling updateDoorData on a door that has no data!") end
local value = door:getDoorData()[member]
if value == nil then
local doorvar = DarkRP.getDoorVarsByName()[member]
net.Start("DarkRP_RemoveDoorVar")
net.WriteUInt(door:EntIndex(), 16)
if not doorvar then
net.WriteUInt(0, 8)
net.WriteString(member)
else
net.WriteUInt(doorvar.id, 8)
end
net.Broadcast()
return
end
net.Start("DarkRP_UpdateDoorData")
net.WriteUInt(door:EntIndex(), 32)
DarkRP.writeNetDoorVar(member, value)
net.Broadcast()
end

View File

@@ -0,0 +1,851 @@
DarkRP.doorToEntIndex = DarkRP.stub{
name = "doorToEntIndex",
description = "Get an ENT index from a door index.",
parameters = {
{
name = "index",
description = "The door index",
type = "number",
optional = false
}
},
returns = {
{
name = "index",
description = "The ENT index",
type = "number",
}
},
metatable = DarkRP
}
DarkRP.doorIndexToEnt = DarkRP.stub{
name = "doorIndexToEnt",
description = "Get the entity of a door index (inverse of ent:doorIndexToEnt()). Note: the door MUST have been created by the map!",
parameters = {
{
name = "index",
description = "The door index",
type = "number",
optional = false
}
},
returns = {
{
name = "door",
description = "The door entity",
type = "Entity",
}
},
metatable = DarkRP
}
DarkRP.writeNetDoorVar = DarkRP.stub{
name = "writeNetDoorVar",
description = "Internal function. You probably shouldn't need this. DarkRP calls this function when sending DoorVar net messages. This function writes the net data for a specific DoorVar.",
parameters = {
{
name = "name",
description = "The name of the DoorVar.",
type = "string",
optional = false
},
{
name = "value",
description = "The value of the DoorVar.",
type = "any",
optional = false
}
},
returns = {
},
metatable = DarkRP
}
DarkRP.ENTITY.doorIndex = DarkRP.stub{
name = "doorIndex",
description = "Get the door index of a door. Use this to store door information in the database.",
parameters = {
},
returns = {
{
name = "index",
description = "The door index.",
type = "number"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.keysLock = DarkRP.stub{
name = "keysLock",
description = "Lock this door or vehicle.",
parameters = {
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.keysUnLock = DarkRP.stub{
name = "keysUnLock",
description = "Unlock this door or vehicle.",
parameters = {
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.addKeysAllowedToOwn = DarkRP.stub{
name = "addKeysAllowedToOwn",
description = "Make this player allowed to co-own the door or vehicle.",
parameters = {
{
name = "ply",
description = "The player to give permission to co-own.",
type = "Player",
optional = false
}
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.addKeysDoorOwner = DarkRP.stub{
name = "addKeysDoorOwner",
description = "Make this player a co-owner of the door.",
parameters = {
{
name = "ply",
description = "The player to add as co-owner.",
type = "Player",
optional = false
}
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.removeKeysDoorOwner = DarkRP.stub{
name = "removeKeysDoorOwner",
description = "Remove this player as co-owner",
parameters = {
{
name = "ply",
description = "The player to remove from the co-owners list.",
type = "Player",
optional = false
}
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.keysOwn = DarkRP.stub{
name = "keysOwn",
description = "Make the player the master owner of the door",
parameters = {
{
name = "ply",
description = "The player set as master owner.",
type = "Player",
optional = false
}
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.keysUnOwn = DarkRP.stub{
name = "keysUnOwn",
description = "Make this player unown the door/vehicle.",
parameters = {
{
name = "ply",
description = "The player.",
type = "Player",
optional = false
}
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.setKeysNonOwnable = DarkRP.stub{
name = "setKeysNonOwnable",
description = "Set whether this door or vehicle is ownable or not.",
parameters = {
{
name = "ownable",
description = "Whether the door or vehicle is blocked from ownership.",
type = "boolean",
optional = false
}
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.setKeysTitle = DarkRP.stub{
name = "setKeysTitle",
description = "Set the title of a door or vehicle.",
parameters = {
{
name = "title",
description = "The title of the door.",
type = "string",
optional = false
}
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.setDoorGroup = DarkRP.stub{
name = "setDoorGroup",
description = "Set the door group of a door.",
parameters = {
{
name = "group",
description = "The door group.",
type = "string",
optional = false
}
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.addKeysDoorTeam = DarkRP.stub{
name = "addKeysDoorTeam",
description = "Allow a team to lock/unlock a door..",
parameters = {
{
name = "team",
description = "The team to add to team owners.",
type = "number",
optional = false
}
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.removeKeysDoorTeam = DarkRP.stub{
name = "removeKeysDoorTeam",
description = "Disallow a team from locking/unlocking a door.",
parameters = {
{
name = "team",
description = "The team to remove from team owners.",
type = "number",
optional = false
}
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.removeAllKeysDoorTeams = DarkRP.stub{
name = "removeAllKeysDoorTeams",
description = "Disallow all teams from locking/unlocking a door.",
parameters = {
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.removeAllKeysExtraOwners = DarkRP.stub{
name = "removeAllKeysExtraOwners",
description = "Remove all co-owners from a door.",
parameters = {
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.removeAllKeysAllowedToOwn = DarkRP.stub{
name = "removeAllKeysAllowedToOwn",
description = "Disallow all people from owning the door.",
parameters = {
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.removeKeysAllowedToOwn = DarkRP.stub{
name = "removeKeysAllowedToOwn",
description = "Remove a player from being allowed to co-own a door.",
parameters = {
{
name = "ply",
description = "The player to be removed.",
type = "Player",
optional = false
}
},
returns = {
},
metatable = DarkRP.ENTITY
}
DarkRP.ENTITY.isLocked = DarkRP.stub{
name = "isLocked",
description = "Whether this door/vehicle is locked.",
parameters = {
},
returns = {
{
name = "answer",
description = "Whether it's locked.",
type = "boolean"
}
},
metatable = DarkRP.ENTITY
}
DarkRP.PLAYER.keysUnOwnAll = DarkRP.stub{
name = "keysUnOwnAll",
description = "Unown every door and vehicle owned by this player.",
parameters = {
},
returns = {
},
metatable = DarkRP.PLAYER
}
DarkRP.PLAYER.sendDoorData = DarkRP.stub{
name = "sendDoorData",
description = "Internal function. Sends all door data to a player.",
parameters = {
},
returns = {
},
metatable = DarkRP.PLAYER
}
DarkRP.PLAYER.doPropertyTax = DarkRP.stub{
name = "doPropertyTax",
description = "Tax a player based on the amount of doors and vehicles they have.",
parameters = {
},
returns = {
},
metatable = DarkRP.PLAYER
}
DarkRP.PLAYER.initiateTax = DarkRP.stub{
name = "initiateTax",
description = "Internal function, starts the timer that taxes the player every once in a while.",
parameters = {
},
returns = {
},
metatable = DarkRP.PLAYER
}
DarkRP.hookStub{
name = "onKeysLocked",
description = "Called when a door or vehicle was locked.",
parameters = {
{
name = "ent",
description = "The entity that was locked.",
type = "Entity"
}
},
returns = {
}
}
DarkRP.hookStub{
name = "onKeysUnlocked",
description = "Called when a door or vehicle was unlocked.",
parameters = {
{
name = "ent",
description = "The entity that was unlocked.",
type = "Entity"
}
},
returns = {
}
}
DarkRP.hookStub{
name = "playerKeysSold",
description = "When a player sold a door or vehicle.",
parameters = {
{
name = "ply",
description = "The player who sold the door or vehicle.",
type = "Player"
},
{
name = "ent",
description = "The entity that was sold.",
type = "Entity"
},
{
name = "GiveMoneyBack",
description = "The amount of money refunded to the player",
type = "number"
}
},
returns = {
}
}
DarkRP.hookStub{
name = "hideSellDoorMessage",
description = "Whether to hide the door/vehicle sold notification",
parameters = {
{
name = "ply",
description = "The player who sold the door or vehicle.",
type = "Player"
},
{
name = "ent",
description = "The entity that was sold.",
type = "Player"
},
},
returns = {
{
name = "hide",
description = "Whether to hide the notification.",
type = "boolean"
}
}
}
DarkRP.hookStub{
name = "getDoorCost",
description = "Get the cost of a door.",
parameters = {
{
name = "ply",
description = "The player who has the intention to purchase the door.",
type = "Player"
},
{
name = "ent",
description = "The door",
type = "Entity"
}
},
returns = {
{
name = "cost",
description = "The price of the door.",
type = "number"
}
}
}
DarkRP.hookStub{
name = "getVehicleCost",
description = "Get the cost of a vehicle.",
parameters = {
{
name = "ply",
description = "The player who has the intention to purchase the vehicle.",
type = "Player"
},
{
name = "ent",
description = "The vehicle",
type = "Entity"
}
},
returns = {
{
name = "cost",
description = "The price of the vehicle.",
type = "number"
}
}
}
DarkRP.hookStub{
name = "playerBuyDoor",
description = "When a player purchases a door.",
parameters = {
{
name = "ply",
description = "The player who is to buy the door.",
type = "Player"
},
{
name = "ent",
description = "The door.",
type = "Entity"
}
},
returns = {
{
name = "allowed",
description = "Whether the player is allowed to buy the door.",
type = "boolean"
},
{
name = "reason",
description = "The reason why a player is not allowed to buy the door, if applicable.",
type = "string"
},
{
name = "surpress",
description = "Whether to show the reason in a notification to the player, return true here to surpress the message.",
type = "boolean"
}
}
}
DarkRP.hookStub{
name = "playerSellDoor",
description = "When a player is about to sell a door.",
parameters = {
{
name = "ply",
description = "The player who is to sell the door.",
type = "Player"
},
{
name = "ent",
description = "The door.",
type = "Entity"
}
},
returns = {
{
name = "allowed",
description = "Whether the player is allowed to sell the door.",
type = "boolean"
},
{
name = "reason",
description = "The reason why a player is not allowed to sell the door, if applicable.",
type = "string"
}
}
}
DarkRP.hookStub{
name = "onAllowedToOwnAdded",
description = "When a player adds a co-owner to a door.",
parameters = {
{
name = "ply",
description = "The player who adds the co-owner.",
type = "Player"
},
{
name = "ent",
description = "The door.",
type = "Entity"
},
{
name = "target",
description = "The target who will be allowed to own the door.",
type = "Player"
}
},
returns = {
{
name = "allowed",
description = "Whether the player is allowed to add this player as co-owner.",
type = "boolean"
}
}
}
DarkRP.hookStub{
name = "onAllowedToOwnRemoved",
description = "When a player removes a co-owner to a door.",
parameters = {
{
name = "ply",
description = "The player who removes the co-owner.",
type = "Player"
},
{
name = "ent",
description = "The door.",
type = "Entity"
},
{
name = "target",
description = "The target who will not be allowed to own the door anymore.",
type = "Player"
}
},
returns = {
{
name = "allowed",
description = "Whether the player is allowed to remove this player as co-owner.",
type = "boolean"
}
}
}
DarkRP.hookStub{
name = "playerBuyVehicle",
description = "When a player purchases a vehicle.",
parameters = {
{
name = "ply",
description = "The player who is to buy the vehicle.",
type = "Player"
},
{
name = "ent",
description = "The vehicle.",
type = "Entity"
}
},
returns = {
{
name = "allowed",
description = "Whether the player is allowed to buy the vehicle.",
type = "boolean"
},
{
name = "reason",
description = "The reason why a player is not allowed to buy the vehicle, if applicable.",
type = "string"
},
{
name = "surpress",
description = "Whether to show the reason in a notification to the player, return true here to surpress the message.",
type = "boolean"
}
}
}
DarkRP.hookStub{
name = "playerSellVehicle",
description = "When a player is about to sell a vehicle.",
parameters = {
{
name = "ply",
description = "The player who is to sell the vehicle.",
type = "Player"
},
{
name = "ent",
description = "The vehicle.",
type = "Entity"
}
},
returns = {
{
name = "allowed",
description = "Whether the player is allowed to sell the vehicle.",
type = "boolean"
},
{
name = "reason",
description = "The reason why a player is not allowed to sell the vehicle, if applicable.",
type = "string"
}
}
}
DarkRP.hookStub{
name = "playerBoughtDoor",
description = "Called when a player has purchased a door.",
parameters = {
{
name = "ply",
description = "The player who has purchased the door.",
type = "Player"
},
{
name = "ent",
description = "The purchased door.",
type = "Entity"
},
{
name = "cost",
description = "The cost of the purchased door.",
type = "number"
}
},
returns = {
}
}
DarkRP.hookStub{
name = "playerBoughtVehicle",
description = "Called when a player has purchased a vehicle.",
parameters = {
{
name = "ply",
description = "The player who has purchased the vehicle.",
type = "Player"
},
{
name = "ent",
description = "The purchased vehicle.",
type = "Entity"
},
{
name = "cost",
description = "The cost of the purchased vehicle.",
type = "number"
}
},
returns = {
}
}
DarkRP.hookStub{
name = "canTax",
description = "Called before a player pays taxes. This hook differs from onPaidTax in that this hook can prevent the taxing and change the tax amount.",
parameters = {
{
name = "ply",
description = "The player who was taxed.",
type = "Player"
},
{
name = "tax",
description = "The amount of money that is about to be taxed from the player.",
type = "number"
}
},
returns = {
{
name = "shouldTax",
description = "Whether the player is to be taxed. Return false here to prevent the player from being taxed.",
type = "boolean"
},
{
name = "tax",
description = "Overrides the amount of money that is taxed.",
type = "number"
}
}
}
DarkRP.hookStub{
name = "onPaidTax",
description = "Called when a player has paid tax.",
parameters = {
{
name = "ply",
description = "The player who was taxed.",
type = "Player"
},
{
name = "tax",
description = "The percentage of tax taken from his wallet.",
type = "number"
},
{
name = "wallet",
description = "The amount of money the player had before the tax was applied.",
type = "number"
}
},
returns = {
}
}
DarkRP.hookStub{
name = "canTaxEntity",
description = "Called right before a player's property is taxed. Decides per entity whether it can be taxed.",
parameters = {
{
name = "ply",
description = "The player whose property will be taxed.",
type = "Player"
},
{
name = "ent",
description = "The door or vehicle that is to be taxed",
type = "Entity"
}
},
returns = {
{
name = "shouldTax",
description = "Return false here to prevent this specific entity from being taxed.",
type = "boolean"
}
}
}
DarkRP.hookStub{
name = "canPropertyTax",
description = "Called right before a player's property is taxed. This hook differs from onPropertyTax in that onPropertyTax is called AFTER the taxing. With this hook, one can influence the taxing process.",
parameters = {
{
name = "ply",
description = "The player whose property will be taxed.",
type = "Player"
},
{
name = "tax",
description = "The amount of money that will be taxed (unless overridden by this hook).",
type = "number"
}
},
returns = {
{
name = "shouldTax",
description = "Return false here to prevent the doors from being taxed.",
type = "boolean"
},
{
name = "taxOverride",
description = "Override the tax amount.",
type = "number"
}
}
}
DarkRP.hookStub{
name = "onPropertyTax",
description = "Called right AFTER a player's property is taxed. Please use canPropertyTax if you want to influence the taxing process.",
parameters = {
{
name = "ply",
description = "The player whose property has been taxed.",
type = "Player"
},
{
name = "tax",
description = "The amount of money that has been taxed.",
type = "number"
},
{
name = "couldAfford",
description = "Whether the player was able to afford the tax.",
type = "boolean"
}
},
returns = {
}
}