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

View File

@@ -0,0 +1,213 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
-- luacheck: globals ACCESS_LABELS
ACCESS_LABELS = {}
ACCESS_LABELS[DOOR_OWNER] = "owner"
ACCESS_LABELS[DOOR_TENANT] = "tenant"
ACCESS_LABELS[DOOR_GUEST] = "guest"
ACCESS_LABELS[DOOR_NONE] = "none"
function PLUGIN:GetDefaultDoorInfo(door)
local owner = IsValid(door:GetDTEntity(0)) and door:GetDTEntity(0) or nil
local name = door:GetNetVar("title", door:GetNetVar("name", IsValid(owner) and L"dTitleOwned" or L"dTitle"))
local description = door:GetNetVar("ownable") and L("dIsOwnable") or L("dIsNotOwnable")
local color = ix.config.Get("color")
local faction = door:GetNetVar("faction")
local class = door:GetNetVar("class")
if (class) then
local classData = ix.class.list[class]
if (classData) then
if (classData.color) then
color = classData.color
end
if (!owner) then
description = L("dOwnedBy", L2(classData.name) or classData.name)
end
end
elseif (faction) then
local info = ix.faction.indices[faction]
color = team.GetColor(faction)
if (info and !owner) then
description = L("dOwnedBy", L2(info.name) or info.name)
end
end
if (owner) then
description = L("dOwnedBy", owner:GetName())
end
return {
name = name,
description = description,
color = color
}
end
function PLUGIN:DrawDoorInfo(door, width, position, angles, scale, clientPosition)
local alpha = math.max((1 - clientPosition:DistToSqr(door:GetPos()) / 65536) * 255, 0)
if (alpha < 1) then
return
end
local info = hook.Run("GetDoorInfo", door) or self:GetDefaultDoorInfo(door)
if (!istable(info) or table.IsEmpty(info)) then
return
end
-- title + background
surface.SetFont("ix3D2DMediumFont")
local nameWidth, nameHeight = surface.GetTextSize(info.name)
derma.SkinFunc("DrawImportantBackground", -width * 0.5, -nameHeight * 0.5,
width, nameHeight, ColorAlpha(info.color, alpha * 0.5))
surface.SetTextColor(ColorAlpha(color_white, alpha))
surface.SetTextPos(-nameWidth * 0.5, -nameHeight * 0.5)
surface.DrawText(info.name)
-- description
local lines = ix.util.WrapText(info.description, width, "ix3D2DSmallFont")
local y = nameHeight * 0.5 + 4
for i = 1, #lines do
local line = lines[i]
local textWidth, textHeight = surface.GetTextSize(line)
surface.SetTextPos(-textWidth * 0.5, y)
surface.DrawText(line)
y = y + textHeight
end
-- background blur
ix.util.PushBlur(function()
cam.Start3D2D(position, angles, scale)
surface.SetDrawColor(11, 11, 11, math.max(alpha - 100, 0))
surface.DrawRect(-width * 0.5, -nameHeight * 0.5, width, y + nameHeight * 0.5 + 4)
cam.End3D2D()
end)
end
function PLUGIN:PostDrawTranslucentRenderables(bDepth, bSkybox)
if (bDepth or bSkybox or !LocalPlayer():GetCharacter()) then
return
end
local entities = ents.FindInSphere(EyePos(), 256)
local clientPosition = LocalPlayer():GetPos()
for _, v in ipairs(entities) do
if (!IsValid(v) or !v:IsDoor() or !v:GetNetVar("visible")) then
continue
end
local color = v:GetColor()
if (v:IsEffectActive(EF_NODRAW) or color.a <= 0) then
continue
end
local position = v:LocalToWorld(v:OBBCenter())
local mins, maxs = v:GetCollisionBounds()
local width = 0
local size = maxs - mins
local trace = {
collisiongroup = COLLISION_GROUP_WORLD,
ignoreworld = true,
endpos = position
}
-- trace from shortest side to center to get correct position for rendering
if (size.z < size.x and size.z < size.y) then
trace.start = position - v:GetUp() * size.z
width = size.y
elseif (size.x < size.y) then
trace.start = position - v:GetForward() * size.x
width = size.y
elseif (size.y < size.x) then
trace.start = position - v:GetRight() * size.y
width = size.x
end
width = math.max(width, 12)
trace = util.TraceLine(trace)
local angles = trace.HitNormal:Angle()
local anglesOpposite = trace.HitNormal:Angle()
angles:RotateAroundAxis(angles:Forward(), 90)
angles:RotateAroundAxis(angles:Right(), 90)
anglesOpposite:RotateAroundAxis(anglesOpposite:Forward(), 90)
anglesOpposite:RotateAroundAxis(anglesOpposite:Right(), -90)
local positionFront = trace.HitPos - (((position - trace.HitPos):Length() * 2) + 1) * trace.HitNormal
local positionOpposite = trace.HitPos + (trace.HitNormal * 2)
if (trace.HitNormal:Dot((clientPosition - position):GetNormalized()) < 0) then
-- draw front
cam.Start3D2D(positionFront, angles, 0.1)
self:DrawDoorInfo(v, width * 8, positionFront, angles, 0.1, clientPosition)
cam.End3D2D()
else
-- draw back
cam.Start3D2D(positionOpposite, anglesOpposite, 0.1)
self:DrawDoorInfo(v, width * 8, positionOpposite, anglesOpposite, 0.1, clientPosition)
cam.End3D2D()
end
end
end
net.Receive("ixDoorMenu", function()
if (IsValid(ix.gui.door)) then
return ix.gui.door:Remove()
end
local door = net.ReadEntity()
local access = net.ReadTable()
local entity = net.ReadEntity()
if (IsValid(door)) then
ix.gui.door = vgui.Create("ixDoorMenu")
ix.gui.door:SetDoor(door, access, entity)
end
end)
net.Receive("ixDoorPermission", function()
local door = net.ReadEntity()
if (!IsValid(door)) then
return
end
local target = net.ReadEntity()
local access = net.ReadUInt(4)
local panel = door.ixPanel
if (IsValid(panel) and IsValid(target)) then
panel.access[target] = access
for _, v in ipairs(panel.access:GetLines()) do
if (v.player == target) then
v:SetColumnText(2, L(ACCESS_LABELS[access or 0]))
return
end
end
end
end)

View File

@@ -0,0 +1,116 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PANEL = {}
local function DoorSetPermission(door, target, permission)
net.Start("ixDoorPermission")
net.WriteEntity(door)
net.WriteEntity(target)
net.WriteUInt(permission, 4)
net.SendToServer()
end
function PANEL:Init()
self:SetSize(280, 240)
self:SetTitle(L"doorSettings")
self:Center()
self:MakePopup()
self.access = self:Add("DListView")
self.access:Dock(FILL)
self.access:AddColumn(L"name").Header:SetTextColor(Color(25, 25, 25))
self.access:AddColumn(L"access").Header:SetTextColor(Color(25, 25, 25))
self.access.OnClickLine = function(this, line, selected)
if (IsValid(line.player)) then
local menu = DermaMenu()
menu:AddOption(L"tenant", function()
if (self.accessData and self.accessData[line.player] != DOOR_TENANT) then
DoorSetPermission(self.door, line.player, DOOR_TENANT)
end
end):SetImage("icon16/user_add.png")
menu:AddOption(L"guest", function()
if (self.accessData and self.accessData[line.player] != DOOR_GUEST) then
DoorSetPermission(self.door, line.player, DOOR_GUEST)
end
end):SetImage("icon16/user_green.png")
menu:AddOption(L"none", function()
if (self.accessData and self.accessData[line.player] != DOOR_NONE) then
DoorSetPermission(self.door, line.player, DOOR_NONE)
end
end):SetImage("icon16/user_red.png")
menu:Open()
for _, v in pairs(menu:GetChildren()[1]:GetChildren()) do
v:SetFont("MenuFontNoClamp")
end
end
end
end
function PANEL:SetDoor(door, access, door2)
door.ixPanel = self
self.accessData = access
self.door = door
for _, v in ipairs(player.GetAll()) do
if (v != LocalPlayer() and v:GetCharacter()) then
self.access:AddLine(v:Name(), L(ACCESS_LABELS[access[v] or 0])).player = v
end
end
if (self:CheckAccess(DOOR_OWNER)) then
self.sell = self:Add("DButton")
self.sell:Dock(BOTTOM)
self.sell:SetText(L"sell")
self.sell:SetTextColor(color_white)
self.sell:DockMargin(0, 5, 0, 0)
self.sell.DoClick = function(this)
self:Remove()
ix.command.Send("doorsell")
end
end
if (self:CheckAccess(DOOR_TENANT)) then
self.name = self:Add("DTextEntry")
self.name:Dock(TOP)
self.name:DockMargin(0, 0, 0, 5)
self.name.Think = function(this)
if (!this:IsEditing()) then
local entity = IsValid(door2) and door2 or door
self.name:SetText(entity:GetNetVar("title", L"dTitleOwned"))
end
end
self.name.OnEnter = function(this)
ix.command.Send("doorsettitle", this:GetText())
end
end
end
function PANEL:CheckAccess(access)
access = access or DOOR_GUEST
if ((self.accessData[LocalPlayer()] or 0) >= access) then
return true
end
return false
end
function PANEL:Think()
if (self.accessData and !IsValid(self.door) and self:CheckAccess()) then
self:Remove()
end
end
vgui.Register("ixDoorMenu", PANEL, "DFrame")

View File

@@ -0,0 +1,211 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
AddCSLuaFile()
if (CLIENT) then
SWEP.PrintName = "Keys"
SWEP.Slot = 0
SWEP.SlotPos = 2
SWEP.DrawAmmo = false
SWEP.DrawCrosshair = false
end
SWEP.Author = "Chessnut"
SWEP.Instructions = "Primary Fire: Lock\nSecondary Fire: Unlock"
SWEP.Purpose = "Hitting things and knocking on doors."
SWEP.Drop = false
SWEP.ViewModelFOV = 45
SWEP.ViewModelFlip = false
SWEP.AnimPrefix = "rpg"
SWEP.ViewTranslation = 4
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = -1
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = ""
SWEP.Primary.Damage = 5
SWEP.Primary.Delay = 0.75
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = 0
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = ""
SWEP.ViewModel = Model("models/weapons/c_arms_animations.mdl")
SWEP.WorldModel = ""
SWEP.UseHands = false
SWEP.LowerAngles = Angle(0, 5, -14)
SWEP.LowerAngles2 = Angle(0, 5, -22)
SWEP.IsAlwaysLowered = true
SWEP.FireWhenLowered = true
SWEP.HoldType = "passive"
-- luacheck: globals ACT_VM_FISTS_DRAW ACT_VM_FISTS_HOLSTER
ACT_VM_FISTS_DRAW = 2
ACT_VM_FISTS_HOLSTER = 1
function SWEP:Holster()
if (!IsValid(self.Owner)) then
return
end
local viewModel = self.Owner:GetViewModel()
if (IsValid(viewModel)) then
viewModel:SetPlaybackRate(1)
viewModel:ResetSequence(ACT_VM_FISTS_HOLSTER)
end
return true
end
function SWEP:Precache()
end
function SWEP:Initialize()
self:SetHoldType(self.HoldType)
end
function SWEP:PrimaryAttack()
local time = ix.config.Get("doorLockTime", 1)
local time2 = math.max(time, 1)
self:SetNextPrimaryFire(CurTime() + time2)
self:SetNextSecondaryFire(CurTime() + time2)
if (!IsFirstTimePredicted()) then
return
end
if (CLIENT) then
return
end
local data = {}
data.start = self.Owner:GetShootPos()
data.endpos = data.start + self.Owner:GetAimVector()*96
data.filter = self.Owner
local entity = util.TraceLine(data).Entity
--[[
Locks the entity if the contiditon fits:
1. The entity is door and client has access to the door.
2. The entity is vehicle and the "owner" variable is same as client's character ID.
--]]
if (IsValid(entity) and
(
(entity:IsDoor() and entity:CheckDoorAccess(self.Owner)) or
(entity:IsVehicle() and entity.CPPIGetOwner and entity:CPPIGetOwner() == self.Owner)
)
) then
self.Owner:SetAction("@locking", time, function()
self:ToggleLock(entity, true)
end)
return
end
end
function SWEP:ToggleLock(door, state)
if (IsValid(self.Owner) and self.Owner:GetPos():Distance(door:GetPos()) > 96) then
return
end
if (door:IsDoor()) then
local partner = door:GetDoorPartner()
if (state) then
if (IsValid(partner)) then
partner:Fire("lock")
end
door:Fire("lock")
self.Owner:EmitSound("doors/door_latch3.wav")
hook.Run("PlayerLockedDoor", self.Owner, door, partner)
else
if (IsValid(partner)) then
partner:Fire("unlock")
end
door:Fire("unlock")
self.Owner:EmitSound("doors/door_latch1.wav")
hook.Run("PlayerUnlockedDoor", self.Owner, door, partner)
end
elseif (door:IsVehicle()) then
if (state) then
door:Fire("lock")
if (door.IsSimfphyscar) then
door.IsLocked = true
end
self.Owner:EmitSound("doors/door_latch3.wav")
hook.Run("PlayerLockedVehicle", self.Owner, door)
else
door:Fire("unlock")
if (door.IsSimfphyscar) then
door.IsLocked = nil
end
self.Owner:EmitSound("doors/door_latch1.wav")
hook.Run("PlayerUnlockedVehicle", self.Owner, door)
end
end
end
function SWEP:SecondaryAttack()
local time = ix.config.Get("doorLockTime", 1)
local time2 = math.max(time, 1)
self:SetNextPrimaryFire(CurTime() + time2)
self:SetNextSecondaryFire(CurTime() + time2)
if (!IsFirstTimePredicted()) then
return
end
if (CLIENT) then
return
end
local data = {}
data.start = self.Owner:GetShootPos()
data.endpos = data.start + self.Owner:GetAimVector()*96
data.filter = self.Owner
local entity = util.TraceLine(data).Entity
--[[
Unlocks the entity if the contiditon fits:
1. The entity is door and client has access to the door.
2. The entity is vehicle and the "owner" variable is same as client's character ID.
]]--
if (IsValid(entity) and
(
(entity:IsDoor() and entity:CheckDoorAccess(self.Owner)) or
(entity:IsVehicle() and entity.CPPIGetOwner and entity:CPPIGetOwner() == self.Owner)
)
) then
self.Owner:SetAction("@unlocking", time, function()
self:ToggleLock(entity, false)
end)
return
end
end

View File

@@ -0,0 +1,509 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLUGIN = PLUGIN
ix.command.Add("DoorSell", {
description = "@cmdDoorSell",
OnRun = function(self, client, arguments)
-- Get the entity 96 units infront of the player.
local data = {}
data.start = client:GetShootPos()
data.endpos = data.start + client:GetAimVector() * 96
data.filter = client
local trace = util.TraceLine(data)
local entity = trace.Entity
-- Check if the entity is a valid door.
if (IsValid(entity) and entity:IsDoor() and !entity:GetNetVar("disabled")) then
-- Check if the player owners the door.
if (client == entity:GetDTEntity(0)) then
entity = IsValid(entity.ixParent) and entity.ixParent or entity
-- Get the price that the door is sold for.
local price = math.Round(entity:GetNetVar("price", ix.config.Get("doorCost")) * ix.config.Get("doorSellRatio"))
local character = client:GetCharacter()
-- Remove old door information.
entity:RemoveDoorAccessData()
local doors = character:GetVar("doors") or {}
for k, v in ipairs(doors) do
if (v == entity) then
table.remove(doors, k)
end
end
character:SetVar("doors", doors, true)
-- Take their money and notify them.
character:GiveMoney(price)
hook.Run("OnPlayerPurchaseDoor", client, entity, false, PLUGIN.CallOnDoorChildren)
ix.log.Add(client, "selldoor")
return "@dSold", ix.currency.Get(price)
else
-- Otherwise tell them they can not.
return "@notOwner"
end
else
-- Tell the player the door isn't valid.
return "@dNotValid"
end
end
})
ix.command.Add("DoorBuy", {
description = "@cmdDoorBuy",
OnRun = function(self, client, arguments)
-- Get the entity 96 units infront of the player.
local data = {}
data.start = client:GetShootPos()
data.endpos = data.start + client:GetAimVector() * 96
data.filter = client
local trace = util.TraceLine(data)
local entity = trace.Entity
-- Check if the entity is a valid door.
if (IsValid(entity) and entity:IsDoor() and !entity:GetNetVar("disabled")) then
if (!entity:GetNetVar("ownable") or entity:GetNetVar("faction") or entity:GetNetVar("class")) then
return "@dNotAllowedToOwn"
end
if (IsValid(entity:GetDTEntity(0))) then
return "@dOwnedBy", entity:GetDTEntity(0):Name()
end
entity = IsValid(entity.ixParent) and entity.ixParent or entity
-- Get the price that the door is bought for.
local price = entity:GetNetVar("price", ix.config.Get("doorCost"))
local character = client:GetCharacter()
-- Check if the player can actually afford it.
if (character:HasMoney(price)) then
-- Set the door to be owned by this player.
entity:SetDTEntity(0, client)
entity.ixAccess = {
[client] = DOOR_OWNER
}
PLUGIN:CallOnDoorChildren(entity, function(child)
child:SetDTEntity(0, client)
end)
local doors = character:GetVar("doors") or {}
doors[#doors + 1] = entity
character:SetVar("doors", doors, true)
-- Take their money and notify them.
character:TakeMoney(price)
hook.Run("OnPlayerPurchaseDoor", client, entity, true, PLUGIN.CallOnDoorChildren)
ix.log.Add(client, "buydoor")
return "@dPurchased", ix.currency.Get(price)
else
-- Otherwise tell them they can not.
return "@canNotAfford"
end
else
-- Tell the player the door isn't valid.
return "@dNotValid"
end
end
})
ix.command.Add("DoorSetUnownable", {
description = "@cmdDoorSetUnownable",
privilege = "Manage Doors",
adminOnly = true,
arguments = ix.type.text,
OnRun = function(self, client, name)
-- Get the door the player is looking at.
local entity = client:GetEyeTrace().Entity
-- Validate it is a door.
if (IsValid(entity) and entity:IsDoor() and !entity:GetNetVar("disabled")) then
-- Set it so it is unownable.
entity:SetNetVar("ownable", nil)
-- Change the name of the door if needed.
if (name:find("%S")) then
entity:SetNetVar("name", name)
end
PLUGIN:CallOnDoorChildren(entity, function(child)
child:SetNetVar("ownable", nil)
if (name:find("%S")) then
child:SetNetVar("name", name)
end
end)
-- Save the door information.
PLUGIN:SaveDoorData()
return "@dMadeUnownable"
else
-- Tell the player the door isn't valid.
return "@dNotValid"
end
end
})
ix.command.Add("DoorSetOwnable", {
description = "@cmdDoorSetOwnable",
privilege = "Manage Doors",
adminOnly = true,
arguments = ix.type.text,
OnRun = function(self, client, name)
-- Get the door the player is looking at.
local entity = client:GetEyeTrace().Entity
-- Validate it is a door.
if (IsValid(entity) and entity:IsDoor() and !entity:GetNetVar("disabled")) then
-- Set it so it is ownable.
entity:SetNetVar("ownable", true)
entity:SetNetVar("visible", true)
-- Update the name.
if (name:find("%S")) then
entity:SetNetVar("name", name)
end
PLUGIN:CallOnDoorChildren(entity, function(child)
child:SetNetVar("ownable", true)
child:SetNetVar("visible", true)
if (name:find("%S")) then
child:SetNetVar("name", name)
end
end)
-- Save the door information.
PLUGIN:SaveDoorData()
return "@dMadeOwnable"
else
-- Tell the player the door isn't valid.
return "@dNotValid"
end
end
})
ix.command.Add("DoorSetFaction", {
description = "@cmdDoorSetFaction",
privilege = "Manage Doors",
adminOnly = true,
arguments = bit.bor(ix.type.text, ix.type.optional),
OnRun = function(self, client, name)
-- Get the door the player is looking at.
local entity = client:GetEyeTrace().Entity
-- Validate it is a door.
if (IsValid(entity) and entity:IsDoor() and !entity:GetNetVar("disabled")) then
if (!name or name == "") then
entity.ixFactionID = nil
entity:SetNetVar("faction", nil)
PLUGIN:CallOnDoorChildren(entity, function()
entity.ixFactionID = nil
entity:SetNetVar("faction", nil)
end)
PLUGIN:SaveDoorData()
return "@dRemoveFaction"
end
local faction
-- Loop through each faction, checking the uniqueID and name.
for k, v in pairs(ix.faction.teams) do
if (ix.util.StringMatches(k, name) or ix.util.StringMatches(L(v.name, client), name)) then
-- This faction matches the provided string.
faction = v
-- Escape the loop.
break
end
end
-- Check if a faction was found.
if (faction) then
entity.ixFactionID = faction.uniqueID
entity:SetNetVar("faction", faction.index)
PLUGIN:CallOnDoorChildren(entity, function()
entity.ixFactionID = faction.uniqueID
entity:SetNetVar("faction", faction.index)
end)
PLUGIN:SaveDoorData()
return "@dSetFaction", L(faction.name, client)
-- The faction was not found.
else
return "@invalidFaction"
end
end
end
})
ix.command.Add("DoorSetDisabled", {
description = "@cmdDoorSetDisabled",
privilege = "Manage Doors",
adminOnly = true,
arguments = ix.type.bool,
OnRun = function(self, client, bDisabled)
-- Get the door the player is looking at.
local entity = client:GetEyeTrace().Entity
-- Validate it is a door.
if (IsValid(entity) and entity:IsDoor()) then
-- Set it so it is ownable.
entity:SetNetVar("disabled", bDisabled)
PLUGIN:CallOnDoorChildren(entity, function(child)
child:SetNetVar("disabled", bDisabled)
end)
PLUGIN:SaveDoorData()
-- Tell the player they have made the door (un)disabled.
return "@dSet" .. (bDisabled and "" or "Not") .. "Disabled"
else
-- Tell the player the door isn't valid.
return "@dNotValid"
end
end
})
ix.command.Add("DoorSetTitle", {
description = "@cmdDoorSetTitle",
arguments = ix.type.text,
OnRun = function(self, client, name)
-- Get the door infront of the player.
local data = {}
data.start = client:GetShootPos()
data.endpos = data.start + client:GetAimVector() * 96
data.filter = client
local trace = util.TraceLine(data)
local entity = trace.Entity
-- Validate the door.
if (IsValid(entity) and entity:IsDoor() and !entity:GetNetVar("disabled")) then
-- Make sure the name contains actual characters.
if (!name:find("%S")) then
return "@invalidArg", 1
end
--[[
NOTE: Here, we are setting two different networked names.
The title is a temporary name, while the other name is the
default name for the door. The reason for this is so when the
server closes while someone owns the door, it doesn't save THEIR
title, which could lead to unwanted things.
--]]
name = name:utf8sub(1, 24)
-- Check if they are allowed to change the door's name.
if (entity:CheckDoorAccess(client, DOOR_TENANT)) then
entity:SetNetVar("title", name)
elseif (CAMI.PlayerHasAccess(client, "Helix - Manage Doors", nil)) then
entity:SetNetVar("name", name)
PLUGIN:CallOnDoorChildren(entity, function(child)
child:SetNetVar("name", name)
end)
PLUGIN:SaveDoorData()
else
-- Otherwise notify the player he/she can't.
return "@notOwner"
end
else
-- Notification of the door not being valid.
return "@dNotValid"
end
end
})
ix.command.Add("DoorSetParent", {
description = "@cmdDoorSetParent",
privilege = "Manage Doors",
adminOnly = true,
OnRun = function(self, client, arguments)
-- Get the door the player is looking at.
local entity = client:GetEyeTrace().Entity
-- Validate it is a door.
if (IsValid(entity) and entity:IsDoor() and !entity:GetNetVar("disabled")) then
client.ixDoorParent = entity
return "@dSetParentDoor"
else
-- Tell the player the door isn't valid.
return "@dNotValid"
end
end
})
ix.command.Add("DoorSetChild", {
description = "@cmdDoorSetChild",
privilege = "Manage Doors",
adminOnly = true,
OnRun = function(self, client, arguments)
-- Get the door the player is looking at.
local entity = client:GetEyeTrace().Entity
-- Validate it is a door.
if (IsValid(entity) and entity:IsDoor() and !entity:GetNetVar("disabled")) then
if (client.ixDoorParent == entity) then
return "@dCanNotSetAsChild"
end
-- Check if the player has set a door as a parent.
if (IsValid(client.ixDoorParent)) then
-- Add the door to the parent's list of children.
client.ixDoorParent.ixChildren = client.ixDoorParent.ixChildren or {}
client.ixDoorParent.ixChildren[entity:MapCreationID()] = true
-- Set the door's parent to the parent.
entity.ixParent = client.ixDoorParent
-- Save the door information.
PLUGIN:SaveDoorData()
PLUGIN:CopyParentDoor(entity)
return "@dAddChildDoor"
else
-- Tell the player they do not have a door parent.
return "@dNoParentDoor"
end
else
-- Tell the player the door isn't valid.
return "@dNotValid"
end
end
})
ix.command.Add("DoorRemoveChild", {
description = "@cmdDoorRemoveChild",
privilege = "Manage Doors",
adminOnly = true,
OnRun = function(self, client, arguments)
-- Get the door the player is looking at.
local entity = client:GetEyeTrace().Entity
-- Validate it is a door.
if (IsValid(entity) and entity:IsDoor() and !entity:GetNetVar("disabled")) then
if (client.ixDoorParent == entity) then
PLUGIN:CallOnDoorChildren(entity, function(child)
child.ixParent = nil
end)
entity.ixChildren = nil
return "@dRemoveChildren"
end
-- Check if the player has set a door as a parent.
if (IsValid(entity.ixParent) and entity.ixParent.ixChildren) then
-- Remove the door from the list of children.
entity.ixParent.ixChildren[entity:MapCreationID()] = nil
-- Remove the variable for the parent.
entity.ixParent = nil
PLUGIN:SaveDoorData()
return "@dRemoveChildDoor"
end
else
-- Tell the player the door isn't valid.
return "@dNotValid"
end
end
})
ix.command.Add("DoorSetHidden", {
description = "@cmdDoorSetHidden",
privilege = "Manage Doors",
adminOnly = true,
arguments = ix.type.bool,
OnRun = function(self, client, bHidden)
-- Get the door the player is looking at.
local entity = client:GetEyeTrace().Entity
-- Validate it is a door.
if (IsValid(entity) and entity:IsDoor()) then
entity:SetNetVar("visible", !bHidden)
PLUGIN:CallOnDoorChildren(entity, function(child)
child:SetNetVar("visible", !bHidden)
end)
PLUGIN:SaveDoorData()
-- Tell the player they have made the door (un)hidden.
return "@dSet" .. (bHidden and "" or "Not") .. "Hidden"
else
-- Tell the player the door isn't valid.
return "@dNotValid"
end
end
})
ix.command.Add("DoorSetClass", {
description = "@cmdDoorSetClass",
privilege = "Manage Doors",
adminOnly = true,
arguments = bit.bor(ix.type.text, ix.type.optional),
OnRun = function(self, client, name)
-- Get the door the player is looking at.
local entity = client:GetEyeTrace().Entity
-- Validate it is a door.
if (IsValid(entity) and entity:IsDoor() and !entity:GetNetVar("disabled")) then
if (!name or name == "") then
entity:SetNetVar("class", nil)
PLUGIN:CallOnDoorChildren(entity, function()
entity:SetNetVar("class", nil)
end)
PLUGIN:SaveDoorData()
return "@dRemoveClass"
end
local class, classData
for k, v in pairs(ix.class.list) do
if (ix.util.StringMatches(v.name, name) or ix.util.StringMatches(L(v.name, client), name)) then
class, classData = k, v
break
end
end
-- Check if a faction was found.
if (class) then
entity.ixClassID = class
entity:SetNetVar("class", class)
PLUGIN:CallOnDoorChildren(entity, function()
entity.ixClassID = class
entity:SetNetVar("class", class)
end)
PLUGIN:SaveDoorData()
return "@dSetClass", L(classData.name, client)
else
return "@invalidClass"
end
end
end
})

View File

@@ -0,0 +1,91 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLUGIN = PLUGIN
PLUGIN.name = "Doors"
PLUGIN.author = "Chessnut"
PLUGIN.description = "A simple door system."
-- luacheck: globals DOOR_OWNER DOOR_TENANT DOOR_GUEST DOOR_NONE
DOOR_OWNER = 3
DOOR_TENANT = 2
DOOR_GUEST = 1
DOOR_NONE = 0
ix.util.Include("sv_plugin.lua")
ix.util.Include("cl_plugin.lua")
ix.util.Include("sh_commands.lua")
do
local entityMeta = FindMetaTable("Entity")
function entityMeta:CheckDoorAccess(client, access)
if (!self:IsDoor()) then
return false
end
access = access or DOOR_GUEST
local parent = self.ixParent
if (IsValid(parent)) then
return parent:CheckDoorAccess(client, access)
end
if (hook.Run("CanPlayerAccessDoor", client, self, access)) then
return true
end
if (self.ixAccess and (self.ixAccess[client] or 0) >= access) then
return true
end
return false
end
if (SERVER) then
function entityMeta:RemoveDoorAccessData()
local receivers = {}
for k, _ in pairs(self.ixAccess or {}) do
receivers[#receivers + 1] = k
end
if (#receivers > 0) then
net.Start("ixDoorMenu")
net.Send(receivers)
end
self.ixAccess = {}
self:SetDTEntity(0, nil)
-- Remove door information on child doors
PLUGIN:CallOnDoorChildren(self, function(child)
child:SetDTEntity(0, nil)
end)
end
end
end
-- Configurations for door prices.
ix.config.Add("doorCost", 10, "The price to purchase a door.", nil, {
data = {min = 0, max = 500},
category = "dConfigName"
})
ix.config.Add("doorSellRatio", 0.5, "How much of the door price is returned when selling a door.", nil, {
data = {min = 0, max = 1.0, decimals = 1},
category = "dConfigName"
})
ix.config.Add("doorLockTime", 1, "How long it takes to (un)lock a door.", nil, {
data = {min = 0, max = 10.0, decimals = 1},
category = "dConfigName"
})

View File

@@ -0,0 +1,304 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
util.AddNetworkString("ixDoorMenu")
util.AddNetworkString("ixDoorPermission")
-- Variables for door data.
local variables = {
-- Whether or not the door will be disabled.
"disabled",
-- The name of the door.
"name",
-- Price of the door.
"price",
-- If the door is ownable.
"ownable",
-- The faction that owns a door.
"faction",
-- The class that owns a door.
"class",
-- Whether or not the door will be hidden.
"visible"
}
function PLUGIN:CallOnDoorChildren(entity, callback)
local parent
if (entity.ixChildren) then
parent = entity
elseif (entity.ixParent) then
parent = entity.ixParent
end
if (IsValid(parent)) then
callback(parent)
for k, _ in pairs(parent.ixChildren) do
local child = ents.GetMapCreatedEntity(k)
if (IsValid(child)) then
callback(child)
end
end
end
end
function PLUGIN:CopyParentDoor(child)
local parent = child.ixParent
if (IsValid(parent)) then
for _, v in ipairs(variables) do
local value = parent:GetNetVar(v)
if (child:GetNetVar(v) != value) then
child:SetNetVar(v, value)
end
end
end
end
-- Called after the entities have loaded.
function PLUGIN:LoadData()
-- Restore the saved door information.
local data = self:GetData()
if (!data) then
return
end
-- Loop through all of the saved doors.
for k, v in pairs(data) do
-- Get the door entity from the saved ID.
local entity = ents.GetMapCreatedEntity(k)
-- Check it is a valid door in-case something went wrong.
if (IsValid(entity) and entity:IsDoor()) then
-- Loop through all of our door variables.
for k2, v2 in pairs(v) do
if (k2 == "children") then
entity.ixChildren = v2
for index, _ in pairs(v2) do
local door = ents.GetMapCreatedEntity(index)
if (IsValid(door)) then
door.ixParent = entity
end
end
elseif (k2 == "combineDoor") then
entity.ixCombineDoor = v2
entity:SetNetVar("combineDoor", v2)
elseif (k2 == "faction") then
for k3, v3 in pairs(ix.faction.teams) do
if (k3 == v2) then
entity.ixFactionID = k3
entity:SetNetVar("faction", v3.index)
break
end
end
else
entity:SetNetVar(k2, v2)
end
end
end
end
end
-- Called before the gamemode shuts down.
function PLUGIN:SaveDoorData()
-- Create an empty table to save information in.
local data = {}
local doors = {}
for _, v in ipairs(ents.GetAll()) do
if (v:IsDoor()) then
doors[v:MapCreationID()] = v
end
end
local doorData
-- Loop through doors with information.
for k, v in pairs(doors) do
-- Another empty table for actual information regarding the door.
doorData = {}
-- Save all of the needed variables to the doorData table.
for _, v2 in ipairs(variables) do
local value = v:GetNetVar(v2)
if (value) then
doorData[v2] = v:GetNetVar(v2)
end
end
if (v.ixChildren) then
doorData.children = v.ixChildren
end
if (v.ixClassID) then
doorData.class = v.ixClassID
end
if (v.ixFactionID) then
doorData.faction = v.ixFactionID
end
if (v.ixCombineDoor) then
doorData.combineDoor = v.ixCombineDoor
end
-- Add the door to the door information.
if (!table.IsEmpty(doorData)) then
data[k] = doorData
end
end
-- Save all of the door information.
self:SetData(data)
end
function PLUGIN:CanPlayerUseDoor(client, entity)
if (entity:GetNetVar("disabled")) then
return false
end
end
-- Whether or not a player a player has any abilities over the door, such as locking.
function PLUGIN:CanPlayerAccessDoor(client, door, access)
local faction = door:GetNetVar("faction")
-- If the door has a faction set which the client is a member of, allow access.
if (faction and client:Team() == faction) then
return true
end
local class = door:GetNetVar("class")
-- If the door has a faction set which the client is a member of, allow access.
local classData = ix.class.list[class]
local charClass = client:GetCharacter():GetClass()
local classData2 = ix.class.list[charClass]
if (class and classData and classData2) then
if (classData.team) then
if (classData.team != classData2.team) then
return false
end
else
if (charClass != class) then
return false
end
end
return true
end
end
function PLUGIN:PostPlayerLoadout(client)
client:Give("ix_keys")
end
function PLUGIN:ShowTeam(client)
local data = {}
data.start = client:GetShootPos()
data.endpos = data.start + client:GetAimVector() * 96
data.filter = client
local trace = util.TraceLine(data)
local entity = trace.Entity
if (IsValid(entity) and entity:IsDoor() and !entity:GetNetVar("faction") and !entity:GetNetVar("class")) then
if (entity:CheckDoorAccess(client, DOOR_TENANT)) then
local door = entity
if (IsValid(door.ixParent)) then
door = door.ixParent
end
if door.ixAccess and istable(door.ixAccess) then
net.Start("ixDoorMenu")
net.WriteEntity(door)
net.WriteTable(door.ixAccess)
net.WriteEntity(entity)
net.Send(client)
end
elseif (!IsValid(entity:GetDTEntity(0))) then
ix.command.Run(client, "doorbuy")
else
client:NotifyLocalized("notAllowed")
end
return true
end
end
function PLUGIN:PlayerLoadedCharacter(client, curChar, prevChar)
if (prevChar) then
local doors = prevChar:GetVar("doors") or {}
for _, v in ipairs(doors) do
if (IsValid(v) and v:IsDoor() and v:GetDTEntity(0) == client) then
v:RemoveDoorAccessData()
end
end
prevChar:SetVar("doors", nil)
end
end
function PLUGIN:PlayerDisconnected(client)
local character = client:GetCharacter()
if (character) then
local doors = character:GetVar("doors") or {}
for _, v in ipairs(doors) do
if (IsValid(v) and v:IsDoor() and v:GetDTEntity(0) == client) then
v:RemoveDoorAccessData()
end
end
character:SetVar("doors", nil)
end
end
net.Receive("ixDoorPermission", function(length, client)
local door = net.ReadEntity()
local target = net.ReadEntity()
local access = net.ReadUInt(4)
if (IsValid(target) and target:GetCharacter() and door.ixAccess and door:GetDTEntity(0) == client and target != client) then
access = math.Clamp(access or 0, DOOR_NONE, DOOR_TENANT)
if (access == door.ixAccess[target]) then
return
end
door.ixAccess[target] = access
local recipient = {}
for k, v in pairs(door.ixAccess) do
if (v > DOOR_GUEST) then
recipient[#recipient + 1] = k
end
end
if (#recipient > 0) then
net.Start("ixDoorPermission")
net.WriteEntity(door)
net.WriteEntity(target)
net.WriteUInt(access, 4)
net.Send(recipient)
end
end
end)