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,27 @@
--[[
| 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/
--]]
netstream.Hook("SetLinkedUpdateCL", function(update)
ix.data.Set("CameraConsoleLinkedUpdate", update)
end)
netstream.Hook("SetConsoleUpdates", function(updates)
if (IsValid(ix.gui.consolePanel)) then
ix.gui.consolePanel.updates = updates
end
end)
netstream.Hook("CloseConsole", function(updates)
if (IsValid(ix.gui.consolePanel)) then
ix.gui.consolePanel:TurnOff()
ix.gui.consolePanel:Remove()
end
end)

View File

@@ -0,0 +1,421 @@
--[[
| 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/
--]]
-- Shared localization panel/hooks
local cameraActive = false
local combineOverlay = false
local cameraNumber = 1
local ButtonColor = Color(248, 248, 255)
local BackgroundColor = Color(0, 0, 0, 250)
local cameraLock = false
local cameras = {}
local cameraCount = #cameras
local PLUGIN = PLUGIN
surface.CreateFont( "CameraFont", {
font = "DebugFixed",
size = SScaleMin(50 / 3),
weight = 50,
blursize = 0,
scanlines = 50,
} )
-- Console Panel
local PANEL = {}
function PANEL:Init()
self:SetSize(SScaleMin(400 / 3), SScaleMin(300 / 3))
self:Center()
self:MakePopup()
Schema:AllowMessage(self)
self.Paint = function(_, w, h)
draw.RoundedBox( 8, 0, 0, w, h, BackgroundColor )
end
self.topPanel = self:Add("Panel")
self.topPanel:Dock(TOP)
self.topPanel:SetTall(SScaleMin(20 / 3))
self.topPanel:DockMargin(SScaleMin(10 / 3), SScaleMin(10 / 3), SScaleMin(10 / 3), SScaleMin(10 / 3))
local line = self:Add("DShape")
line:SetType("Rect")
line:Dock(TOP)
line:SetTall(1)
line:SetColor(color_white)
line:DockMargin(SScaleMin(10 / 3), 0, SScaleMin(10 / 3), SScaleMin(10 / 3))
self:GetAllCameras()
self:CreateCloseButton()
self:CreateTitle()
self:CreateButtons()
end
function PANEL:CreateCloseButton()
local close = self.topPanel:Add("DButton")
close:Dock(RIGHT)
close:SetWide(SScaleMin(20 / 3))
close:SetText("")
close.Paint = function(_, w, h)
surface.SetDrawColor(color_white)
surface.SetMaterial(ix.util.GetMaterial("willardnetworks/tabmenu/navicons/exit-grey.png"))
surface.DrawTexturedRect(0, 0, w, h)
end
close.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
self:TurnOff()
self:Remove()
end
end
function PANEL:CreateTitle()
local combineText = self.topPanel:Add("DLabel")
combineText:Dock(LEFT)
combineText:SetFont("DebugFixedRadio")
combineText:SetText(">:: ")
combineText:SetContentAlignment(4)
combineText:SizeToContents()
self.title = self.topPanel:Add("DLabel")
self.title:Dock(LEFT)
self.title:SetFont("DebugFixedRadio")
self.title:SetText("COMMAND CONSOLE")
self.title:SetContentAlignment(4)
self.title:SizeToContents()
end
function PANEL:CreateButtons()
netstream.Start("GetLinkedUpdate")
self.buttonlist = {}
self.buttongrid = self:Add("DGrid")
self.buttongrid:Dock(FILL)
self.buttongrid:DockMargin(SScaleMin(10 / 3), 0, SScaleMin(10 / 3), 0)
self.buttongrid:SetCols(1)
self.buttongrid:SetColWide(self:GetWide() - SScaleMin(20 / 3))
self.buttongrid:SetRowHeight( SScaleMin(50 / 3) )
local function CreateButton(parent, text, bAddToButtonList)
parent:SetText(string.utf8upper(text))
parent:SetSize(self:GetWide() - SScaleMin(20 / 3), SScaleMin(40 / 3))
parent:SetTextColor(color_black)
parent:SetFont("DebugFixedRadio")
parent.Paint = function(_, w, h)
draw.RoundedBox( 8, 0, 0, w, h, ButtonColor )
end
if bAddToButtonList then
self.buttongrid:AddItem(parent)
self:AddToButtonList(parent)
end
end
self.thirdperson = false
local cameraButton = vgui.Create("DButton")
CreateButton(cameraButton, "cameras", true)
cameraButton.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
if cameraCount >= 1 then
cameraActive = true
combineOverlay = true
if ix.option.Get("thirdpersonEnabled") then
self.thirdperson = true
ix.option.Set("thirdpersonEnabled", false)
end
self:SetVisible(false)
self:CreateCameraUI()
self:AddPVS()
end
end
local character = LocalPlayer():GetCharacter()
local class = character:GetClass()
if (class == CLASS_CP_CMD or class == CLASS_CP_CPT or class == CLASS_CP_RL or class == CLASS_OVERSEER or class == CLASS_OW_SCANNER) then
netstream.Start("GetConsoleUpdates", self.entity)
local addLink = vgui.Create("DButton")
CreateButton(addLink, "link update", true)
addLink.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
local chooseUpdatePanel = vgui.Create("DFrame")
chooseUpdatePanel:SetSize(SScaleMin(300 / 3), SScaleMin(500 / 3))
chooseUpdatePanel:Center()
chooseUpdatePanel:SetTitle("Wybierz aktualizację")
DFrameFixer(chooseUpdatePanel)
local scrollPanel = chooseUpdatePanel:Add("DScrollPanel")
scrollPanel:Dock(FILL)
for _, v in pairs(self.updates) do
local button = scrollPanel:Add("DButton")
button:Dock(TOP)
button:SetTall(SScaleMin(50 / 3))
button:SetFont("DebugFixedRadio")
button:SetText(string.utf8sub( v.update_text, 1, 20 ).."... - "..v.update_poster)
button.Paint = function(_, w, h)
surface.SetDrawColor(Color(0, 0, 0, 100))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
surface.DrawOutlinedRect(0, 0, w, h)
end
button.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
netstream.Start("SetLinkedUpdate", self.entity, v.update_text)
chooseUpdatePanel:Remove()
end
end
end
end
local updates = vgui.Create("DButton")
CreateButton(updates, "updates", true)
updates.DoClick = function()
if !ix.data.Get("CameraConsoleLinkedUpdate") then
LocalPlayer():NotifyLocalized("Brak powiązanej aktualizacji")
return
end
local updatePanel = vgui.Create("DFrame")
updatePanel:SetSize(SScaleMin(600 / 3), SScaleMin(700 / 3))
updatePanel:Center()
updatePanel:MakePopup()
Schema:AllowMessage(updatePanel)
updatePanel:SetTitle("Update")
DFrameFixer(updatePanel)
updatePanel.lblTitle:SetFont("MenuFontNoClamp")
updatePanel.lblTitle:SizeToContents()
local htmlPanel = updatePanel:Add("HTML")
htmlPanel:Dock(FILL)
local string = "<p style='font-family: Open Sans; font-size: "..tostring(SScaleMin(13 / 3)).."; color: rgb(41,243,229);'>"..tostring(ix.data.Get("CameraConsoleLinkedUpdate")).."</p>"
if istable(ix.data.Get("CameraConsoleLinkedUpdate")) then
if table.IsEmpty(ix.data.Get("CameraConsoleLinkedUpdate")) then
string = "<p style='font-family: Open Sans; font-size: "..tostring(SScaleMin(13 / 3)).."; color: rgb(41,243,229);'>Brak aktualizacji.</p>"
end
end
local html = string.Replace(string, "\n", "<br>")
htmlPanel:SetHTML(html)
htmlPanel.Paint = function(_, w, h)
surface.SetDrawColor(40, 88, 115, 75)
surface.DrawRect(0, 0, w, h)
end
end
end
netstream.Hook("ReplyCrimeReports", function(crimes)
if ix.gui.datapadCrimes and IsValid(ix.gui.datapadCrimes) then
ix.gui.datapadCrimes:CreateCrimes(crimes)
end
end)
function PANEL:CreateCameraUI()
local cameraPanel = vgui.Create( "Panel" )
cameraPanel:SetPos( ScrW() / 2 + SScaleMin(350 / 3), ScrH() / 2 + SScaleMin(280 / 3))
cameraPanel:SetSize( SScaleMin(200 / 3), SScaleMin(100 / 3) )
cameraPanel:MakePopup()
Schema:AllowMessage(cameraPanel)
local CameraUI3 = vgui.Create( "Panel", cameraPanel )
CameraUI3:SetPos( ScrW() / 2 + SScaleMin(350 / 3), ScrH() / 2 + SScaleMin(110 / 3))
CameraUI3:SetSize( SScaleMin(200 / 3), SScaleMin(150 / 3) )
local back = cameraPanel:Add("DButton")
back:Dock(TOP)
back:SetTextColor(color_black)
back:SetTall(SScaleMin(20 / 3))
back:SetFont("DebugFixedRadio")
back:SetText("Powrót")
back.Paint = function(_, w, h)
surface.SetDrawColor(color_white)
surface.SetMaterial(ix.util.GetMaterial("willardnetworks/tabmenu/navicons/exit-grey.png"))
surface.DrawTexturedRect(0, 0, w, h)
end
back.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
self:CameraOff()
cameraPanel:Remove()
self:SetVisible(true)
if self.thirdperson then
ix.option.Set("thirdpersonEnabled", true)
end
end
local nextCamera = vgui.Create( "DButton", cameraPanel )
nextCamera:SetText( "Następne" )
nextCamera:SetFont("DebugFixedRadio")
nextCamera:SetTextColor( Color(0, 0, 0, 255) )
nextCamera:SetPos( SScaleMin(105 / 3), SScaleMin(30 / 3) )
nextCamera:SetSize( SScaleMin(75 / 3), SScaleMin(25 / 3) )
nextCamera.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
if cameraNumber < cameraCount then
cameraNumber = cameraNumber + 1
self:AddPVS()
end
end
local previousCamera = vgui.Create( "DButton", cameraPanel )
previousCamera:SetText( "Poprzednie" )
previousCamera:SetFont("DebugFixedRadio")
previousCamera:SetTextColor( Color(0, 0, 0, 255) )
previousCamera:SetPos( SScaleMin(20 / 3), SScaleMin(30 / 3) )
previousCamera:SetSize( SScaleMin(75 / 3), SScaleMin(25 / 3) )
previousCamera.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
if cameraNumber > 1 then
cameraNumber = cameraNumber - 1
self:AddPVS()
end
end
local LockCamera = vgui.Create( "DButton", cameraPanel )
LockCamera:SetText( "Zablokuj" )
LockCamera:SetFont("DebugFixedRadio")
LockCamera:SetTextColor( Color(0, 0, 0, 255) )
LockCamera:SetPos( SScaleMin(20 / 3), SScaleMin(60 / 3) )
LockCamera:SetSize( SScaleMin(75 / 3), SScaleMin(25 / 3) )
LockCamera.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
cameraLock = !cameraLock
end
local List = vgui.Create( "DPanelList", CameraUI3 )
List:SetSize(SScaleMin(190 / 3), SScaleMin(120 / 3))
List:SetSpacing( SScaleMin(5 / 3) )
List:SetPos(SScaleMin(5 / 3), SScaleMin(15 / 3))
List:EnableHorizontal( false )
List:EnableVerticalScrollbar( true )
for k, _ in pairs(cameras) do
local Spawnd = vgui.Create("DButton", List)
Spawnd:SetText("Kamera "..k)
Spawnd:SetFont("DebugFixedRadio")
Spawnd:SetTextColor( Color(0, 0, 0, 255) )
Spawnd:SetSize( SScaleMin(75 / 3), SScaleMin(25 / 3) )
Spawnd.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
cameraNumber = k
self:AddPVS()
end
Spawnd.Paint = function()
draw.RoundedBox( 8, 0, 0, Spawnd:GetWide(), Spawnd:GetTall(), ButtonColor )
end
List:AddItem( Spawnd )
end
local Elements = { cameraPanel; CameraUI3; back; nextCamera; previousCamera; LockCamera}
for k,v in pairs(Elements) do
if k > 2 then
v.Paint = function()
draw.RoundedBox( 8, 0, 0, v:GetWide(), v:GetTall(), ButtonColor )
end
else
v.Paint = function()
draw.RoundedBox( 8, 0, 0, v:GetWide(), v:GetTall(), BackgroundColor )
end
end
end
end
function PANEL:AddToButtonList(button)
if button then
if self.buttonlist then
if istable(self.buttonlist) then
table.insert(self.buttonlist, button)
end
end
end
end
function PANEL:CameraOff()
cameraActive = false
combineOverlay = false
cameraNumber = 1
cameraLock = false
end
function PANEL:TurnOff()
netstream.Start("CloseConsole", self.entity)
end
function PANEL:AddPVS()
netstream.Start("SetConsoleCameraPos", self.entity, cameras[cameraNumber])
end
function PANEL:GetAllCameras()
if !table.IsEmpty(cameras) then
table.Empty(cameras)
end
for _, v in pairs(ents.GetAll()) do
if (v:GetClass() == "npc_combine_camera" or v:GetClass() == "npc_turret_ceiling") then
table.insert(cameras, v)
end
end
cameraCount = #cameras
end
vgui.Register("ConsolePanel", PANEL, "Panel")
-- Hooks
local function DrawCombineOverlay()
if combineOverlay then
DrawMaterialOverlay( "effects/combine_binocoverlay.vmt", 0.1 )
surface.SetTextColor( 255, 0, 0, 255 )
surface.SetTextPos( SScaleMin(100 / 3), SScaleMin(75 / 3) )
surface.SetFont("CameraFont")
surface.DrawText( "Kamera ".. cameraNumber )
end
end
hook.Add( "RenderScreenspaceEffects", "ConsoleCameraOverlay", DrawCombineOverlay )
local function CalculateConsoleCameraView( client, pos, angles, fov )
if cameraActive then
if cameraCount >= 1 then
if cameras[cameraNumber]:IsValid() then
local BoneIndex = cameras[cameraNumber]:LookupAttachment("eyes")
local Bone = cameras[cameraNumber]:GetAttachment( BoneIndex )
local view = {}
if cameraLock == false then
view.origin = Bone.Pos + cameras[cameraNumber]:GetForward() * 6
view.angles = Bone.Ang
view.fov = fov
view.vm_origin = LocalPlayer():GetForward() * -100
else
view.origin = cameras[cameraNumber]:GetPos() + cameras[cameraNumber]:GetUp() * -50 + cameras[cameraNumber]:GetForward() * 30
view.angles = cameras[cameraNumber]:GetAngles() + Angle(10,0,0)
view.fov = fov
view.vm_origin = LocalPlayer():GetForward() * -100
end
return view
end
end
end
end
hook.Add( "CalcView", "CalculateConsoleCameraView", CalculateConsoleCameraView )

View File

@@ -0,0 +1,12 @@
--[[
| 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/
--]]
ix.util.IncludeDir("ixhl2rp/plugins/combineutilities/consoles/derma", true)

View File

@@ -0,0 +1,70 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLUGIN = PLUGIN
netstream.Hook("SetLinkedUpdate", function(client, console, update)
if (IsValid(console) and console:GetClass() == "ix_console" and console.user == client) then
local character = client:GetCharacter()
if (character:GetClass() != CLASS_CP_CMD and character:GetClass() != CLASS_CP_CPT and character:GetClass() != CLASS_CP_RL and character:GetClass() != CLASS_OVERSEER) then
return
end
ix.data.Set("CameraConsoleLinkedUpdate", update)
netstream.Start(client, "SetLinkedUpdateCL", update)
end
end)
netstream.Hook("GetLinkedUpdate", function(client)
if !client:GetActiveCombineSuit() then
return false
end
local update = ix.data.Get("CameraConsoleLinkedUpdate", {})
netstream.Start(client, "SetLinkedUpdateCL", update)
end)
-- Netstream Hooks
netstream.Hook("CloseConsole", function(client, console)
if (IsValid(console) and console:GetClass() == "ix_console" and console.user == client) then
console:CloseConsole()
end
end)
netstream.Hook("SetConsoleCameraPos", function(client, console, entity)
if !client:GetActiveCombineSuit() then
return false
end
if (IsValid(console) and console:GetClass() == "ix_console" and console.user == client) then
client.currentCamera = entity
end
end)
netstream.Hook("GetConsoleUpdates", function(client)
local character = client:GetCharacter()
local class = character:GetClass()
if (class == CLASS_CP_CPT or class == CLASS_OVERSEER or class == CLASS_OW_SCANNER) then
PLUGIN:GetConsoleUpdates(client)
timer.Simple(0.05, function()
netstream.Start(client, "SetConsoleUpdates", PLUGIN.updatelist)
end)
end
end)
local function CloseConsole(client)
if (IsValid(client.ixConsole)) then
client.ixConsole:CloseConsole()
netstream.Start(client, "CloseConsole")
end
end
hook.Add("PlayerDisconnected", "ixConsoleCloseOnDisconnect", CloseConsole)
hook.Add("PlayerLoadedCharacter", "ixConsoleCloseOnCharSwap", CloseConsole)
hook.Add("PlayerDeath", "ixConsoleCloseOnDeath", CloseConsole)

View File

@@ -0,0 +1,60 @@
--[[
| 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
local ix = ix
include('shared.lua')
netstream.Hook("OpenComputer", function(activeComputer, activeComputerUsers, activeComputerNotes, groupmessages, hasDiskInserted)
LocalPlayer().activeComputer = activeComputer
LocalPlayer().activeComputer.hasDiskInserted = hasDiskInserted
LocalPlayer().activeComputerUsers = activeComputerUsers
LocalPlayer().activeComputerNotes = activeComputerNotes
netstream.Start("SyncStoredNewspapers")
local base = vgui.Create("CitizenComputer")
ix.gui.medicalComputer.groupMessages = groupmessages or {}
end)
-- function ENT:Draw()
-- self:DrawModel()
-- local ang = self:GetAngles()
-- local pos = self:GetPos() + ang:Up() * 12 + ang:Right() * 10 + ang:Forward() * 11.75
-- ang:RotateAroundAxis(ang:Right(), -85.6)
-- ang:RotateAroundAxis(ang:Up(), 90)
-- local width, height = 200, 170
-- local display = self.Displays[self:GetDisplay()] or self.Displays[6]
-- cam.Start3D2D( pos, ang, 0.1 )
-- render.PushFilterMin(TEXFILTER.NONE)
-- render.PushFilterMag(TEXFILTER.NONE)
-- surface.SetDrawColor( Color( 16, 16, 16, 240 ) )
-- surface.DrawRect( 0, 0, width, height )
-- surface.SetDrawColor( Color( 255, 255, 255, 16 ) )
-- surface.DrawRect( 10, height / 2 + math.sin( CurTime() * 4 ) * height / 2.5, width - 22, 1 )
-- local alpha = 191 + 64 * math.sin( CurTime() * 4 )
-- local color = ColorAlpha(display[2], alpha)
-- draw.SimpleText( "Computer", "MenuFont", width / 2, 25, Color( 255, 255, 255, alpha ), TEXT_ALIGN_CENTER )
-- draw.SimpleText( display[1], "MenuFont", width / 2, height - 35, Color( 255, 255, 180, alpha ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER )
-- render.PopFilterMin()
-- render.PopFilterMag()
-- cam.End3D2D()
-- end

View File

@@ -0,0 +1,73 @@
--[[
| 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 timer = timer
local IsValid = IsValid
AddCSLuaFile( "cl_init.lua" ) -- Make sure clientside
AddCSLuaFile( "shared.lua" ) -- and shared scripts are sent.
include("shared.lua")
function ENT:SetProperSkin()
self:SetSkin(0)
end
function ENT:SaveMedicalComputers()
ix.saveEnts:SaveEntity(self)
end
function ENT:Use(client)
if (client.CantPlace) then
client:NotifyLocalized("Musisz poczekać, zanim będziesz mógł tego użyć!")
return false
end
client.CantPlace = true
timer.Simple(3, function()
if (client) then
client.CantPlace = false
end
end)
if (self:GetNWInt("owner") == nil) then
self:SetNWInt("owner", client:GetCharacter():GetID())
end
if (!self.canUse) then
return
end
self:EmitSound( "buttons/button1.wav" )
self.canUse = false
if (client:GetCharacter():GetGroup()) then
self:GetGroupInformation(client, client:GetCharacter(), true)
else
netstream.Start(client, "OpenComputer", self, self.users, self.notes, false, self.hasDiskInserted)
end
self:SetDisplay(2)
local uniqueID = "computer_"..self:EntIndex().."_charcheck"
timer.Create(uniqueID, 10, 0, function()
if (!IsValid(self)) then
timer.Remove(uniqueID)
return
elseif (!IsValid(client) or !client:GetCharacter()) then
self.canUse = true
self:SetDisplay(1)
timer.Remove(uniqueID)
end
end)
end

View File

@@ -0,0 +1,22 @@
--[[
| 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
ENT.Type = "anim"
ENT.Author = "Fruity"
ENT.Base = "ix_medical_computer"
ENT.PrintName = "Computer"
ENT.Category = "HL2 RP"
ENT.Spawnable = true
ENT.AdminOnly = true
ENT.PhysgunDisable = true
ENT.bNoPersist = true

View File

@@ -0,0 +1,43 @@
--[[
| 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
include('shared.lua')
function ENT:Draw()
self:DrawModel() -- Draw the model
local ang = self:GetAngles()
local pos = self:GetPos() + ang:Up() * 48 + ang:Right() * 9.8 + ang:Forward() * -2.38
ang:RotateAroundAxis(ang:Right(), -90)
ang:RotateAroundAxis(ang:Up(), 90)
ang:RotateAroundAxis( ang:Forward(), -48 )
cam.Start3D2D( pos, ang, 0.1 )
local width, height = 155, 80
surface.SetDrawColor( Color( 255, 255, 255, 16 ) )
surface.DrawRect( 0, height / 2 + math.sin( CurTime() * 4 ) * height / 2, width, 1 )
local alpha = 191 + 64 * math.sin( CurTime() * 4 )
draw.SimpleText( "Konsola poleceń", "MenuFont", width / 2, 15, Color( 255, 255, 255, alpha ), TEXT_ALIGN_CENTER )
draw.SimpleText( "Oczekiwanie na użytkownika", "MenuFont", width / 2, height - 25, Color( 255, 255, 180, alpha ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER )
cam.End3D2D()
end
netstream.Hook("OpenConsoleGUI", function(entity)
ix.gui.consolePanel = vgui.Create("ConsolePanel")
ix.gui.consolePanel.entity = entity
end)

View File

@@ -0,0 +1,156 @@
--[[
| 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
AddCSLuaFile( "cl_init.lua" ) -- Make sure clientside
AddCSLuaFile( "shared.lua" ) -- and shared scripts are sent.
include('shared.lua')
function ENT:Initialize()
self:SetModel( "models/props_combine/combine_interface001.mdl" )
self:SetSubMaterial(1, "phoenix_storms/black_chrome")
self:SetSolid(SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:PhysicsInit( SOLID_VPHYSICS )
self:SetUseType(SIMPLE_USE)
self.canUse = true
local physObj = self:GetPhysicsObject()
if (IsValid(physObj)) then
physObj:EnableMotion(false)
physObj:Wake()
end
if table.Count(ents.FindByClass("ix_console")) == 1 then
self:SetName("ix_console_master")
end
ix.saveEnts:SaveEntity(self)
end
function ENT:Use(client)
if (self.canUse) then
if ((!IsValid(self.user) or self.user == client) and client:GetActiveCombineSuit()) then
self.user = client
client.ixConsole = self
self:EmitSound("buttons/button19.wav", 75)
netstream.Start(client, "OpenConsoleGUI", self)
ix.combineNotify:AddNotification("LOG:// Konsola poleceń została użyta przez " .. client:GetCombineTag(), nil, client)
else
self.canUse = false
self:EmitSound("buttons/button8.wav", 75)
timer.Simple(1, function()
self.canUse = true
end)
end
end
end
function ENT:AcceptInput(input, activator, caller, data)
if (!caller.lastTarget or caller.lastTarget != activator) then
caller.lastTarget = activator
end
if (input == "Alert" and self:GetName() == "ix_console_master") then
local character = activator:GetCharacter()
if (activator:IsPlayer() and character and character:GetGenericdata() and !isnumber(character:GetGenericdata())) then
local genericData = character:GetGenericdata()
local cid = character:GetCid() or "N/A"
local name = string.utf8upper(character:GetName()) or "N/A"
if (genericData.anticitizen) then
if (genericData.anticitizen == true) then
caller:Fire("SetAngry", 0, 0)
ix.combineNotify:AddImportantNotification("WRN:// Wizja na Antyobywatelu " .. name .. ", #" .. cid, nil, activator, activator:GetPos())
end
end
if (genericData.bol) then
if (genericData.bol == true) then
caller:Fire("SetAngry", 0, 0)
ix.combineNotify:AddImportantNotification("WRN:// Wizja na BOLu " .. name .. ", #" .. cid, Color(255, 255, 0, 255), activator, activator:GetPos())
end
end
if (activator:Team() == FACTION_VORT and character:GetBackground() != "Biotyk" and character:GetBackground() != "Kolaborator") then
local items = character:GetInventory():GetItems()
local shackles = false
local hooks = false
local collar = false
for itemID, itemData in pairs(items) do
if (ix.item.instances[itemID]:GetData("equip")) then
if (ix.item.instances[itemID].uniqueID == "vortigaunt_slave_shackles_fake") then
shackles = true
elseif (ix.item.instances[itemID].uniqueID == "vortigaunt_slave_hooks_fake") then
hooks = true
elseif (ix.item.instances[itemID].uniqueID == "vortigaunt_slave_collar_fake") then
collar = true
end
end
end
if (!shackles or !hooks or !collar) then
caller:Fire("SetAngry", 0, 0)
ix.combineNotify:AddImportantNotification("WRN:// Wizja na niezarejestrowanym Biotyku #" .. cid, Color(255, 0, 0, 255), activator, activator:GetPos())
end
end
end
if (activator:IsPlayer() and activator:IsRunning()) then
caller:Fire("SetAngry", 0, 0)
end
end
end
function ENT:OnRemove()
if IsValid(self.user) then
self.user.currentCamera = nil
end
self.user = nil
end
function ENT:CloseConsole()
if (IsValid(self.user)) then
self.user.currentCamera = nil
end
self.user = nil
end
-- Hooks
local function SetupCameraVis(client, entity)
if IsValid(client.currentCamera) then
AddOriginToPVS(client.currentCamera:GetPos())
end
end
hook.Add("SetupPlayerVisibility", "ConsoleCameraVisual", SetupCameraVis)
local function OnCameraCreated(entity)
if !entity or entity and !IsValid(entity) then return end
if (entity:GetClass() == "npc_combine_camera") then
timer.Simple(1, function()
if !entity or entity and !IsValid(entity) then return end
entity:SetHealth(100)
end)
entity:Fire("AddOutput", "OnFoundEnemy ix_console:Alert")
--ix.saveEnts:SaveEntity(entity)
end
end
hook.Add("OnEntityCreated", "OnCameraCreated", OnCameraCreated)

View File

@@ -0,0 +1,28 @@
--[[
| 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
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Console"
ENT.Author = "Fruity"
ENT.Contact = ""
ENT.Purpose = ""
ENT.Instructions = "Fruitybooty"
ENT.Category = "HL2 RP"
ENT.Spawnable = true
ENT.AdminOnly = true
ENT.PhysgunDisable = true
ENT.bNoPersist = true

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
include('shared.lua')
netstream.Hook("OpenMedicalComputer", function(activeComputer, activeComputerUsers, activeComputerNotes, groupmessages, hasDiskInserted)
LocalPlayer().activeComputer = activeComputer
LocalPlayer().activeComputer.hasDiskInserted = hasDiskInserted
LocalPlayer().activeComputerUsers = activeComputerUsers
LocalPlayer().activeComputerNotes = activeComputerNotes
netstream.Start("SyncStoredNewspapers")
ix.gui.medicalComputer = vgui.Create("MedicalComputerBase")
ix.gui.medicalComputer.groupMessages = groupmessages or {}
end)
netstream.Hook("SyncStoredNewspapersClient", function(stored)
local writingPlugin = ix.plugin.list["writing"]
writingPlugin.storedNewspapers = stored
end)
netstream.Hook("createMedicalRecords", function(table, resultName, searchname, resultID)
LocalPlayer().activeComputerRecords = table
LocalPlayer().activeComputerResultName = resultName
LocalPlayer().activeComputerSearchName = searchname
LocalPlayer().activeComputerResultID = resultID
end)
function ENT:Initialize()
self:StartShittyComputerSound()
end
function ENT:StartShittyComputerSound()
local uniqueID = "MedicalAmbientSound_"..self:EntIndex()
local time = 1
timer.Simple(1, function()
timer.Adjust(uniqueID, 8)
end)
timer.Create(uniqueID, time, 0, function()
if (IsValid(self)) then
self:EmitSound( "willardnetworks/datapad/computerloop.wav", 65, 100, 0.15)
else
timer.Remove(uniqueID)
end
end)
end
-- function ENT:Draw()
-- self:DrawModel()
-- local ang = self:GetAngles()
-- local pos = self:GetPos() + ang:Up() * 12 + ang:Right() * 10 + ang:Forward() * 11.75
-- ang:RotateAroundAxis(ang:Right(), -85.6)
-- ang:RotateAroundAxis(ang:Up(), 90)
-- local width, height = 200, 170
-- local display = self.Displays[self:GetDisplay()] or self.Displays[6]
-- cam.Start3D2D( pos, ang, 0.1 )
-- render.PushFilterMin(TEXFILTER.NONE)
-- render.PushFilterMag(TEXFILTER.NONE)
-- surface.SetDrawColor( Color( 16, 16, 16, 240 ) )
-- surface.DrawRect( 0, 0, width, height )
-- surface.SetDrawColor( Color( 255, 255, 255, 16 ) )
-- surface.DrawRect( 10, height / 2 + math.sin( CurTime() * 4 ) * height / 2.5, width - 22, 1 )
-- local alpha = 191 + 64 * math.sin( CurTime() * 4 )
-- draw.SimpleText( "Medical Computer", "MenuFont", width / 2, 25, Color( 255, 255, 255, alpha ), TEXT_ALIGN_CENTER )
-- draw.SimpleText( display[1], "MenuFont", width / 2, height - 35, Color( 255, 255, 180, alpha ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER )
-- render.PopFilterMin()
-- render.PopFilterMag()
-- cam.End3D2D()
-- end

View File

@@ -0,0 +1,395 @@
--[[
| 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
AddCSLuaFile( "cl_init.lua" ) -- Make sure clientside
AddCSLuaFile( "shared.lua" ) -- and shared scripts are sent.
include('shared.lua')
util.AddNetworkString( "TypeSound" )
util.AddNetworkString( "ClickSound" )
function ENT:Initialize()
self:SetModel("models/willardnetworks/props/willard_computer.mdl")
self:SetSolid(SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:PhysicsInit( SOLID_VPHYSICS )
self:DrawShadow(false)
self:SetUseType(SIMPLE_USE)
self:SetDisplay(1)
local physics = self:GetPhysicsObject()
physics:EnableMotion(true)
physics:Wake()
timer.Simple(1, function()
if IsValid(self) and physics then
physics:EnableMotion(false)
end
end)
self.canUse = true
self.users = {}
self.notes = {}
self:SaveMedicalComputers()
-- self:SpawnProps()
self:SetProperSkin()
self.hasDiskInserted = false
end
function ENT:SetProperSkin()
self:SetSkin(1)
end
function ENT:SaveMedicalComputers()
ix.saveEnts:SaveEntity(self)
end
function ENT:CloseMedicalComputer()
self:SetDisplay(3)
self:EmitSound("ambient/machines/combine_terminal_idle1.wav")
timer.Remove("computer_"..self:EntIndex().."_charcheck")
timer.Simple(2, function()
if IsValid(self) then
self:SetDisplay(1)
self.canUse = true
end
end)
end
-- function ENT:SpawnProps()
-- local rightFrom = Vector(-20 * self:GetRight(), 0, 0)
-- local leftFrom = Vector(20 * self:GetRight(), 0, 0)
-- local forwardFrom = Vector(20 * self:GetForward(), 0, 0)
-- local aBitDown = Vector(0, 0, 3)
-- local cabinet = ents.Create("prop_dynamic")
-- cabinet:SetPos(self:GetPos() + leftFrom - aBitDown)
-- cabinet:SetAngles(self:GetAngles())
-- cabinet:SetModel("models/props_lab/harddrive02.mdl")
-- cabinet:Activate()
-- cabinet:SetParent(self)
-- cabinet:Spawn()
-- cabinet:DeleteOnRemove(self)
-- local keyboard = ents.Create("prop_dynamic")
-- keyboard:SetPos(self:GetPos() + forwardFrom - (aBitDown * 4.5))
-- keyboard:SetAngles(self:GetAngles())
-- keyboard:SetModel("models/props_c17/computer01_keyboard.mdl")
-- keyboard:Activate()
-- keyboard:SetParent(self)
-- keyboard:Spawn()
-- keyboard:DeleteOnRemove(self)
-- local mouse = ents.Create("prop_dynamic")
-- mouse:SetPos(self:GetPos() + forwardFrom + rightFrom - (aBitDown * 4.3))
-- mouse:SetAngles(self:GetAngles() + Angle(20, -80, 0))
-- mouse:SetModel("models/gibs/shield_scanner_gib1.mdl")
-- mouse:SetMaterial("phoenix_storms/dome")
-- mouse:Activate()
-- mouse:SetParent(self)
-- mouse:Spawn()
-- mouse:DeleteOnRemove(self)
-- end
function ENT:GetGroupInformation(client, character, bNormal)
self.groupmessages = {}
self.groupmessages["messages"] = {}
self.groupmessages["replies"] = {}
local messageQuery = mysql:Select("ix_comgroupmessages")
messageQuery:Select("message_id")
messageQuery:Select("message_text")
messageQuery:Select("message_date")
messageQuery:Select("message_poster")
messageQuery:Select("message_groupid")
messageQuery:Where("message_groupid", character:GetGroupID())
messageQuery:Callback(function(result)
self.groupmessages["messages"] = result or {}
local replyQuery = mysql:Select("ix_comgroupreplies")
replyQuery:Select("reply_id")
replyQuery:Select("reply_text")
replyQuery:Select("reply_date")
replyQuery:Select("reply_poster")
replyQuery:Select("reply_parent")
replyQuery:Select("reply_groupid")
replyQuery:Where("reply_groupid", character:GetGroupID())
replyQuery:Callback(function(result2)
self.groupmessages["replies"] = result2 or {}
if !bNormal then
netstream.Start(client, "OpenMedicalComputer", self, self.users, self.notes, self.groupmessages, self.hasDiskInserted)
else
netstream.Start(client, "OpenComputer", self, self.users, self.notes, self.groupmessages, self.hasDiskInserted)
end
end)
replyQuery:Execute()
end)
messageQuery:Execute()
end
function ENT:Use(client)
if (client.CantPlace) then
client:NotifyLocalized("Musisz poczekać, zanim będziesz mógł tego użyć!")
return false
end
client.CantPlace = true
timer.Simple(3, function()
if (client) then
client.CantPlace = false
end
end)
local character = client:GetCharacter()
if (self:GetNWInt("owner") == nil) then
self:SetNWInt("owner", character:GetID())
end
if !self.canUse then
return
end
self:EmitSound( "buttons/button1.wav" )
self.canUse = false
if (character:GetGroup()) then
self:GetGroupInformation(client, character, false)
else
netstream.Start(client, "OpenMedicalComputer", self, self.users, self.notes, false, self.hasDiskInserted)
end
self:SetDisplay(2)
local uniqueID = "computer_"..self:EntIndex().."_charcheck"
timer.Create(uniqueID, 10, 0, function()
if (!IsValid(self)) then
timer.Remove(uniqueID)
return
elseif (!IsValid(client) or !client:GetCharacter()) then
self.canUse = true
self:SetDisplay(1)
timer.Remove(uniqueID)
end
end)
end
function ENT:AddUser(cid)
if (self.users) then
if (istable(self.users)) then
table.insert(self.users, cid)
end
end
end
function ENT:AddNote(name, text, headline)
self.notes[#self.notes + 1] = {
text = text,
headline = headline,
date = ix.date.GetFormatted("%d/%m/%Y"),
poster = name
}
end
function ENT:UpdateNote(name, text, headline, key)
if !text then self.notes[key] = nil return end
self.notes[key] = {
text = text,
headline = headline,
date = ix.date.GetFormatted("%d/%m/%Y"),
poster = name
}
end
function ENT:OnRemove()
if timer.Exists("MedicalAmbientSound_"..self:EntIndex()) then
timer.Remove("MedicalAmbientSound_"..self:EntIndex())
end
end
function ENT:CheckIfUserHasAccess(client)
if client:HasActiveCombineSuit() then return true end
local character = client:GetCharacter()
local inventory = character:GetInventory()
local invItems = inventory:GetItems()
for _, v in pairs(self.users) do
for _, v2 in pairs(invItems) do
if v2.uniqueID != "id_card" then
continue
end
if tostring(v) == tostring(v2:GetData("cid")) then
return true
end
end
end
client:Notify("You do not have access or you are not wearing a combine suit.")
return false
end
netstream.Hook("AddComputerUser", function(client, activeComputer, cid)
if table.IsEmpty(activeComputer.users) then activeComputer:AddUser(cid) return end
if activeComputer:CheckIfUserHasAccess(client) then
activeComputer:AddUser(cid)
else
return false
end
end)
netstream.Hook("searchMedicalFile", function(client, searchname, activeComputer)
if !activeComputer:CheckIfUserHasAccess(client) then
return false
end
local curTime = CurTime()
if (client.nextSearchMedicalFile and client.nextSearchMedicalFile > curTime) then
return
end
client.nextSearchMedicalFile = curTime + 2
local query = mysql:Select("ix_characters")
query:Select("id")
query:Select("name")
query:Select("cid")
query:WhereLike(((tonumber(searchname) != nil and string.utf8len( searchname ) <= 5) and "cid" or "name"), searchname)
query:Where("schema", Schema and Schema.folder or "helix")
query:Limit(1)
query:Callback(function(result)
if (!istable(result)) then
netstream.Start(client, "createMedicalRecords", false, false, false, false)
return
end
if not result[1] then
netstream.Start(client, "createMedicalRecords", false, false, false, false)
return
end
local dataQuery = mysql:Select("ix_characters_data")
dataQuery:Select("data")
dataQuery:Where("id", result[1].id)
dataQuery:Where("key", "datafilemedicalrecords")
dataQuery:Callback(function(dataResult)
if (!istable(dataResult)) then
netstream.Start(client, "createMedicalRecords", false, false, false, false)
return
end
if not dataResult[1] then
netstream.Start(client, "createMedicalRecords", false, false, false, false)
return
end
local medicalrecords = util.JSONToTable(dataResult[1].data or "")
timer.Simple(0.05, function()
netstream.Start(client, "createMedicalRecords", medicalrecords, result[1].name, searchname, result[1].id)
end)
end)
dataQuery:Execute()
end)
query:Execute()
end)
netstream.Hook("MedicalComputerAddRecord", function(client, id, posterName, text, activeComputer)
if !activeComputer:CheckIfUserHasAccess(client) then
return false
end
id = tonumber(id)
local dataQuery = mysql:Select("ix_characters_data")
dataQuery:Select("data")
dataQuery:Where("id", id)
dataQuery:Where("key", "datafilemedicalrecords")
dataQuery:Callback(function(dataResult)
if (!istable(dataResult)) then
return
end
if not dataResult[1] then
return
end
local medicalrecords = util.JSONToTable(dataResult[1].data or "")
medicalrecords[#medicalrecords + 1] = {
text = text,
date = os.date("%d/%m/%Y"),
poster = posterName
}
if (ix.char.loaded[id]) then
ix.char.loaded[id]:SetDatafilemedicalrecords(medicalrecords)
ix.char.loaded[id]:Save()
else
local updateQuery = mysql:Update("ix_characters_data")
updateQuery:Update("data", util.TableToJSON(medicalrecords))
updateQuery:Where("id", id)
updateQuery:Where("key", "datafilemedicalrecords")
updateQuery:Execute()
end
end)
dataQuery:Execute()
end)
netstream.Hook("MedicalComputerAddNote", function(client, activeComputer, posterName, text, headline)
if !activeComputer:CheckIfUserHasAccess(client) then
return false
end
activeComputer:AddNote(posterName, text, headline)
end)
netstream.Hook("MedicalComputerUpdateNote", function(client, activeComputer, posterName, text, headline, key)
if !activeComputer:CheckIfUserHasAccess(client) then
return false
end
activeComputer:UpdateNote(posterName, text, headline, key)
end)
net.Receive( "TypeSound", function( length, client )
client:EmitSound(string.format( "ambient/machines/keyboard%d_clicks.wav", math.random( 6 ) ),75)
end )
net.Receive( "ClickSound", function( length, client )
client:EmitSound("willardnetworks/datapad/mouseclick.wav", 75)
end )
netstream.Hook("CloseMedicalComputer", function(client, activeComputer)
if activeComputer then
activeComputer:CloseMedicalComputer()
end
end)
netstream.Hook("SyncStoredNewspapers", function(client)
local writingPlugin = ix.plugin.list["writing"]
local storedNewspapers = writingPlugin.storedNewspapers
netstream.Start(client, "SyncStoredNewspapersClient", storedNewspapers)
end)

View File

@@ -0,0 +1,32 @@
--[[
| 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
ENT.Type = "anim"
ENT.Author = "Fruity"
ENT.PrintName = "Medical Computer"
ENT.Category = "HL2 RP"
ENT.Spawnable = true
ENT.AdminOnly = true
ENT.PhysgunDisable = true
ENT.bNoPersist = true
ENT.Displays = {
[1] = {"OCZEKIWANIE", Color( 255, 255, 180 ), true},
[2] = {"POBIERANIE INFORMACJI", Color(0, 255, 0)},
[3] = {"PRZEŁADOWYWANIE", Color(255, 200, 0)},
[4] = {"OFFLINE", Color(255, 0, 0), true}
}
function ENT:SetupDataTables()
self:NetworkVar("Int", 0, "Display")
end

View File

@@ -0,0 +1,82 @@
--[[
| 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
include('shared.lua')
netstream.Hook("OpenTerminal", function(idCardId, genericData, activeCID, credits, entity, messages)
LocalPlayer().idCardId = idCardId
LocalPlayer().idCardCredits = credits
LocalPlayer().activeTerminal = entity
LocalPlayer().genericData = genericData
LocalPlayer().activeCID = activeCID
if istable(messages) then
LocalPlayer().messageList = messages
else
messages = {}
LocalPlayer().messageList = messages
end
vgui.Create("ixTerminal")
end)
netstream.Hook("OpenCIDSelectorTerminal", function(entity)
LocalPlayer().activeTerminal = entity
local cidSelector = vgui.Create("CIDSelector")
cidSelector.activeEntity = entity
cidSelector.ExitCallback = function()
netstream.Start("ClosePanelsTerminal", LocalPlayer().activeTerminal)
LocalPlayer().activeTerminal = nil
LocalPlayer().genericData = nil
LocalPlayer().activeCID = nil
LocalPlayer().messageList = nil
end
cidSelector.SelectCallback = function(idCardID, cid, cidName, entity)
netstream.Start("SelectCIDTerminal", idCardID, cid, cidName, entity)
end
end)
function ENT:Draw()
self:DrawModel()
local width, height = 200, 120
local ang = self:GetAngles()
local pos = self:GetPos() + ang:Up() * 31.2 + ang:Right() * 13 + ang:Forward() * 3.1
ang:RotateAroundAxis(ang:Right(), 94)
ang:RotateAroundAxis(ang:Up(), 90)
ang:RotateAroundAxis(ang:Forward(), 180)
local display = self.Displays[self:GetDisplay()] or self.Displays[6]
cam.Start3D2D( pos, ang, 0.1 )
render.PushFilterMin(TEXFILTER.NONE)
render.PushFilterMag(TEXFILTER.NONE)
surface.SetDrawColor( Color( 16, 16, 16, 140 ) )
surface.DrawRect( 0, 0, width, height )
surface.SetDrawColor( Color( 255, 255, 255, 16 ) )
surface.DrawRect( 0, height / 2 + math.sin( CurTime() * 4 ) * height / 2, width, 1 )
local alpha = 191 + 64 * math.sin( CurTime() * 4 )
local color = ColorAlpha(display[2], alpha)
draw.SimpleText( "Terminal Obywatelski", "MenuFont", width / 2, 25, Color( 255, 255, 255, alpha ), TEXT_ALIGN_CENTER )
draw.SimpleText(display[1], "MenuFont", width / 2, height * 0.5, color, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
render.PopFilterMin()
render.PopFilterMag()
cam.End3D2D()
end

View File

@@ -0,0 +1,452 @@
--[[
| 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
AddCSLuaFile( "cl_init.lua" ) -- Make sure clientside
AddCSLuaFile( "shared.lua" ) -- and shared scripts are sent.
include('shared.lua')
function ENT:Initialize()
self:SetModel(self.model)
self:SetSolid(SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:PhysicsInit( SOLID_VPHYSICS )
self:DrawShadow(false)
self:SetUseType(SIMPLE_USE)
self:SetDisplay(1)
local physics = self:GetPhysicsObject()
if (physics) then
physics:EnableMotion(false)
physics:Wake()
end
self.canUse = true
self:SaveTerminalLocations()
self:OnInitialize()
end
function ENT:OnInitialize()
end
function ENT:SaveTerminalLocations()
ix.saveEnts:SaveEntity(self)
end
function ENT:CheckGlobalUse(client)
if client.CantPlace then
client:NotifyLocalized("Musisz poczekać, zanim będziesz mógł tego użyć!")
return false
end
client.CantPlace = true
timer.Simple(3, function()
if client then
client.CantPlace = false
end
end)
return true
end
function ENT:CheckLocalUse(client)
if (!self.canUse and IsValid(self.activePlayer) and self.activePlayer:GetCharacter() == self.activeCharacter) then
return false
else
self.canUse = false
self.activePlayer = client
self.activeCharacter = client:GetCharacter()
return true
end
end
function ENT:Use(client)
if !self:CheckGlobalUse(client) then
return false
end
if !self:CheckLocalUse(client) then
return false
end
self:OnUse(client)
end
function ENT:OnUse(client)
self:CheckForCID(client)
end
function ENT:SetGroups(bUse)
if bUse then
self:SetBodygroup(2, 1)
self:SetSkin(1)
else
self:SetBodygroup(2, 0)
self:SetSkin(0)
end
end
function ENT:CheckForCID(client)
if (ix.config.Get("creditsNoConnection")) then
self.canUse = false
self:SetGroups(true)
self:SetDisplay(2)
self:EmitSound("buttons/button4.wav")
timer.Simple(10, function()
if (!IsValid(self)) then return end
self:SetDisplay(5)
self:EmitSound("hl1/fvox/buzz.wav", 60, 100, 0.5)
timer.Simple(5, function()
if (!IsValid(self)) then return end
self.canUse = true
self:SetDisplay(1)
self:SetGroups(false)
end)
end)
return
end
local idCards = self.activeCharacter:GetInventory():GetItemsByUniqueID("id_card")
if (#idCards > 1) then
self:OpenCIDSelector(client)
return
end
if (#idCards == 1) then
self:SetGroups(true)
idCards[1]:LoadOwnerGenericData(self.OpenTerminal, self.OpenTerminalFail, client, self)
else
self.canUse = false
self:EmitSound("buttons/button2.wav")
timer.Simple(1, function()
if (IsValid(self)) then
self.canUse = true
end
end)
end
end
function ENT:OpenCIDSelector(client)
netstream.Start(client, "OpenCIDSelectorTerminal", self)
end
netstream.Hook("SelectCIDTerminal", function(client, idCardID, _, _, activeTerminal)
if (IsValid(activeTerminal)) then
local idCard = ix.item.instances[idCardID]
if (!idCard) then
activeTerminal.OpenTerminalFail(nil, client, activeTerminal)
else
idCard:LoadOwnerGenericData(activeTerminal.OpenTerminal, activeTerminal.OpenTerminalFail, client, activeTerminal)
end
end
end)
netstream.Hook("ClosePanelsTerminal", function(client, activeTerminal)
if (IsValid(activeTerminal)) then
activeTerminal.OpenTerminalFail(nil, client, activeTerminal)
end
activeTerminal.genericDataCredits = nil
activeTerminal.genericDataCommunion = nil
activeTerminal.activeCID = nil
end)
function ENT.OpenTerminalFail(idCard, client, activeTerminal)
if (!IsValid(activeTerminal)) then return end
activeTerminal:SetDisplay(4)
activeTerminal:EmitSound("ambient/machines/combine_terminal_idle1.wav")
activeTerminal:SetGroups(false)
timer.Simple(2, function()
if IsValid(activeTerminal) then
activeTerminal:SetDisplay(1)
activeTerminal.canUse = true
end
end)
end
function ENT.OpenTerminal(idCard, genericData, client, activeTerminal)
if (!IsValid(activeTerminal)) then return end
activeTerminal:SetGroups(true)
activeTerminal:EmitSound("buttons/button4.wav")
activeTerminal:SetDisplay(2)
if (activeTerminal:CheckForVerdicts(client, idCard, genericData)) then
timer.Simple(2, function()
if table.IsEmpty(genericData) then
activeTerminal:SetDisplay(8)
activeTerminal:EmitSound("buttons/button2.wav")
timer.Simple(2, function()
if IsValid(activeTerminal) then
activeTerminal:SetDisplay(1)
activeTerminal.canUse = true
end
end)
else
activeTerminal:OnSuccess(idCard, genericData, client)
end
end)
end
end
function ENT:IsSocialOrCohesion(character, genericData)
if (character:IsVortigaunt()) then
if (genericData.cohesionPoints) then
return genericData.cohesionPoints
else
return genericData.socialCredits
end
else
return genericData.socialCredits
end
end
function ENT:OnSuccess(idCard, genericData, client)
local character = client:GetCharacter()
self:SetDisplay(7)
self:EmitSound("ambient/machines/combine_terminal_idle3.wav")
self.genericDataCommunion = genericData.bypassCommunion
self.activeCID = idCard:GetData("cid")
genericData.socialCredits = !genericData.combine and math.Clamp(tonumber(self:IsSocialOrCohesion(character, genericData)), 0, 200) or tonumber(self:IsSocialOrCohesion(character, genericData))
self.genericDataCredits = genericData.socialCredits
local query = mysql:Select("ix_camessaging")
query:Select("message_cid")
query:Select("message_text")
query:Select("message_date")
query:Select("message_poster")
query:Select("message_reply")
query:Where("message_cid", idCard:GetData("cid"))
query:Callback(function(result)
if (character:IsVortigaunt()) then
if (genericData.cid or character:GetBackground() == "Kolaborator") then
ix.combineNotify:AddNotification("LOG:// Podmiot " .. string.upper("identyfikator zasobu biotyczynego:") .. " #" .. genericData.cid .. " użył Terminala Obywatelskiego", nil, client)
else
ix.combineNotify:AddNotification("LOG:// Podmiot " .. string.upper("obroża zasobu biotycznego:") .. " #" .. character:GetCollarID() .. " użył Terminala Obywatelskiego", nil, client)
end
else
ix.combineNotify:AddNotification("LOG:// Podmiot '" .. genericData.name .. "' użył Terminala Obywatelskiego", nil, client)
end
if (!istable(result)) then
netstream.Start(client, "OpenTerminal", idCard:GetID(), genericData, idCard:GetData("cid"), idCard:GetCredits(), self)
return
end
netstream.Start(client, "OpenTerminal", idCard:GetID(), genericData, idCard:GetData("cid"), idCard:GetCredits(), self, result)
end)
query:Execute()
end
function ENT:CheckForVerdicts(client, idCard, genericData)
if (idCard:GetData("active", false) == false) then
self:CreateCombineAlert(client, "WRN:// Wykryto próbę użycia nieaktywnego CID #" .. idCard:GetData("cid", 00000))
self:SetDisplay(8)
timer.Simple(1.5, function()
if self then
self.OpenTerminalFail(nil, client, self)
end
end)
return
end
local isBOL = genericData.bol
local isAC = genericData.anticitizen
if (isBOL or isAC) then
local text = isBOL and "Podejrzanego BOL" or "Antyobywatela"
self:CreateCombineAlert(client, "WRN:// Wykryto aktywność identyfikatora " .. text)
if isAC then
self:SetDisplay(8)
timer.Simple(1.5, function()
if self then
self.OpenTerminalFail(nil, client, self)
end
end)
end
return !isAC -- stop if isAC, continue for isBOL
end
return true
end
function ENT:CreateCombineAlert(client, message)
ix.combineNotify:AddImportantNotification(message, nil, client, self:GetPos())
end
function ENT.CheckIdCardCoupon(idCard, genericData, client, entity, couponAmount)
local character = client:GetCharacter()
if entity:IDCardCheck(idCard, genericData, client, entity) then
entity:EmitSound("ambient/levels/labs/coinslot1.wav")
if (ix.config.Get("creditsNoConnection")) then
entity:SetDisplay(2)
entity.canUse = false
timer.Simple(10, function()
if (!IsValid(entity)) then return end
entity:SetDisplay(5)
entity:EmitSound("buttons/combine_button_locked.wav")
timer.Simple(5, function()
if (!IsValid(entity)) then return end
entity:SetDisplay(1)
entity.canUse = true
end)
timer.Simple(2, function()
if (!IsValid(entity)) then return end
entity:EmitSound("ambient/levels/labs/coinslot1.wav")
end)
end)
return
end
timer.Simple(1, function()
if IsValid(entity) then
entity:EmitSound("Friends/friend_online.wav")
end
end)
entity:SetDisplay(2)
entity.canUse = false
timer.Simple(2, function()
if IsValid(entity) then
if ix.city.main:HasCredits(couponAmount) then
entity:EmitSound("Friends/friend_join.wav")
entity:SetDisplay(4)
idCard:GiveCredits(couponAmount, "Rations", "Ration Coupon")
ix.city.main:TakeCredits(couponAmount)
else
entity:SetDisplay(2)
entity.canUse = false
timer.Simple(10, function()
if (!IsValid(entity)) then return end
entity:SetDisplay(5)
entity:EmitSound("buttons/combine_button_locked.wav")
timer.Simple(5, function()
if (!IsValid(entity)) then return end
entity:SetDisplay(1)
entity.canUse = true
end)
timer.Simple(2, function()
if (!IsValid(entity)) then return end
entity:EmitSound("ambient/levels/labs/coinslot1.wav")
end)
end)
return
end
if ix.item.instances[client.ixCouponUsed] then
ix.item.instances[client.ixCouponUsed]:Remove()
end
client.ixCouponUsed = nil
ix.log.Add(client, "rationsCoupon", couponAmount)
timer.Simple(2, function()
if IsValid(entity) then
entity:SetDisplay(1)
entity.canUse = true
end
end)
end
end)
end
end
function ENT.CheckIdError(idCard, client, entity)
entity:DisplayError(INVALID_CID)
client.ixCouponUsed = nil
end
function ENT:IDCardCheck(idCard, genericData, client, entity)
if (idCard:GetData("active", false) == false) then
entity:CreateCombineAlert(client, "WRN:// Wykryto próbę użycia nieaktywnego CID #" .. idCard:GetData("cid", 00000), FREQ_LIMIT)
return false
end
local isBOL = genericData.bol
local isAC = genericData.anticitizen
if (isBOL or isAC) then
local text = isBOL and "Podejrzanego BOL" or "Antyobywatela"
entity:CreateCombineAlert(client, "WRN:// Wykryto aktywność identyfikatora " .. text, isAC and FREQ_LIMIT)
-- only halt if isAC, allow it to continue for BOL
if (isAC) then
return false
end
end
return true
end
netstream.Hook("AddCAMessage", function(client, name, cid, text, activeTerminal)
if !text or !name or !cid then return false end
if cid != activeTerminal.activeCID then
return false
end
if activeTerminal.genericDataCredits < ix.config.Get("communionSCRequirement", 150) and !activeTerminal.genericDataCommunion then
return false
end
local timestamp = os.date( "%d.%m.%Y" )
local queryObj = mysql:Insert("ix_camessaging")
queryObj:Insert("message_poster", name)
queryObj:Insert("message_text", text)
queryObj:Insert("message_date", timestamp)
queryObj:Insert("message_cid", cid)
queryObj:Execute()
ix.combineNotify:AddNotification("LOG:// Podmiot '" .. name .. "' wysłał wiadomość za pomocą terminala komunikacyjnego", nil, client)
for _, v in pairs(player.GetAll()) do
if !IsValid(v) then continue end
local character = v:GetCharacter()
if !character then continue end
local inventory = character:GetInventory()
if !inventory:HasItem("capda") then continue end
v:Notify("Ktoś właśnie wysłał wiadomość przez terminal komunikacyjny!")
end
end)
netstream.Hook("RemoveCAMessage", function(client, id)
if !id then return false end
if !client:GetCharacter():GetFaction() != FACTION_ADMIN then return false end
local queryObj = mysql:Delete("ix_camessaging")
queryObj:Where("message_id", id)
queryObj:Execute()
end)
netstream.Hook("BreakAttemptSpottedTerminal", function(client, name, cid, activeTerminal)
if cid != activeTerminal.activeCID then
return false
end
ix.combineNotify:AddImportantNotification("WRN:// Próba 51b; Uszkodzenie mienia publicznego", nil, client, client:GetPos())
end)

View File

@@ -0,0 +1,43 @@
--[[
| 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
ENT.Type = "anim"
ENT.PrintName = "Terminal Obywatelski"
ENT.Author = "Fruity"
ENT.Contact = "Willard Networks"
ENT.Purpose = "View datafile info and more via entity."
ENT.Instructions = "Press E"
ENT.Category = "HL2 RP"
ENT.Spawnable = true
ENT.AdminOnly = true
ENT.PhysgunDisable = true
ENT.bNoPersist = true
ENT.model = "models/willardnetworks/props/civilterminal7.mdl"
ENT.canMalfunction = true
ENT.Displays = {
[1] = {"OCZEKIWANIE NA CID", Color( 255, 255, 180 ), true},
[2] = {"WERYFIKOWANIE", Color(255, 200, 0)},
[3] = {"POBIERANIE INFORMACJI", Color(0, 255, 0)},
[4] = {"PRZEŁADOWYWANIE", Color(255, 200, 0)},
[5] = {"OFFLINE", Color(255, 0, 0), true},
[6] = {"OCZEKIWANIE NA CID", Color( 255, 255, 180 )},
[7] = {"PRZYGOTOWYWANIE", Color(0, 255, 0)},
[8] = {"BRAK INFORMACJI", Color(0, 255, 0)}
}
function ENT:SetupDataTables()
self:NetworkVar("Int", 0, "Display")
end

View File

@@ -0,0 +1,606 @@
--[[
| 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
if (SERVER) then
AddCSLuaFile("shared.lua")
end
SWEP.PrintName = "Datapad Kombinatu"
SWEP.Category = "Half-Life 2"
SWEP.Spawnable= true
SWEP.AdminSpawnable= true
SWEP.AdminOnly = false
SWEP.ViewModelFOV = 70
SWEP.ViewModel = "models/weapons/c_slam.mdl"
SWEP.WorldModel = "models/weapons/w_slam.mdl"
SWEP.ShowViewModel = false
SWEP.ShowWorldModel = false
SWEP.ViewModelFlip = false
SWEP.BobScale = 1
SWEP.SwayScale = 0
SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom = false
SWEP.Weight = 0
SWEP.Slot = 0
SWEP.SlotPos = 1
SWEP.UseHands = true
SWEP.FireWhenLowered = true
SWEP.FiresUnderwater = true
SWEP.DrawAmmo = false
SWEP.CSMuzzleFlashes = 1
SWEP.Base = "weapon_base"
SWEP.IsAlwaysRaised = true
SWEP.HoldType = "knife"
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.Secondary.Delay = 0.5
SWEP.MaxOffFlat = 80 -- Maximum degrees off of flat to be.
SWEP.LastFire = 0
SWEP.IronSightsPos = Vector(0, 0, 0)
SWEP.IronSightsAng = Vector(0, 0, 0)
SWEP.ViewModelBoneMods = {
["Slam_base"] = { scale = Vector(0.001, 0.001, 0.001), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) },
["Detonator"] = { scale = Vector(0.001, 0.001, 0.001), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) }
}
SWEP.VElements = {
["v_element"] = { type = "Model", model = "models/fruity/tablet/tablet_sfm.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(7.068, 2.714, -1.198), angle = Angle(75.973, -119.392, 180), size = Vector(1, 1, 2), color = Color(255, 255, 255, 255), surpresslightning = false, material = "", skin = 3, bodygroup = {} }
}
SWEP.WElements = {
["w_element"] = { type = "Model", model = "models/fruity/tablet/tablet_sfm.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(3.901, 5.111, -0.477), angle = Angle(36.905, -180, -178.631), size = Vector(0.8, 0.8, 0.8), color = Color(255, 255, 255, 255), surpresslightning = false, material = "", skin = 3, bodygroup = {} }
}
function SWEP:Initialize()
self:SetHoldType( self.HoldType )
if CLIENT then
-- Create a new table for every weapon instance
self.VElements = table.FullCopy( self.VElements )
self.WElements = table.FullCopy( self.WElements )
self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods )
self:SetHoldType( self.HoldType )
self:CreateModels(self.VElements) -- create viewmodels
self:CreateModels(self.WElements) -- create worldmodels
-- init view model bone build function
if IsValid(self.Owner) then
local vm = self.Owner:GetViewModel()
if IsValid(vm) then
self:ResetBonePositions(vm)
-- Init viewmodel visibility
if (self.ShowViewModel == nil or self.ShowViewModel) then
vm:SetColor(Color(255,255,255,255))
else
-- we set the alpha to 1 instead of 0 because else ViewModelDrawn stops being called
vm:SetColor(Color(255,255,255,1))
-- ^ stopped working in GMod 13 because you have to do Entity:SetRenderMode(1) for translucency to kick in
-- however for some reason the view model resets to render mode 0 every frame so we just apply a debug material to prevent it from drawing
vm:SetMaterial("Debug/hsv")
end
end
end
end
end
----------------------------------------------------
if CLIENT then
SWEP.vRenderOrder = nil
function SWEP:ViewModelDrawn()
local vm = self.Owner:GetViewModel()
if !IsValid(vm) then return end
if (!self.VElements) then return end
self:UpdateBonePositions(vm)
if (!self.vRenderOrder) then
-- we build a render order because sprites need to be drawn after models
self.vRenderOrder = {}
for k, v in pairs( self.VElements ) do
if (v.type == "Model") then
table.insert(self.vRenderOrder, 1, k)
elseif (v.type == "Sprite" or v.type == "Quad") then
table.insert(self.vRenderOrder, k)
end
end
end
for _, name in ipairs( self.vRenderOrder ) do
local v = self.VElements[name]
if (!v) then self.vRenderOrder = nil break end
if (v.hide) then continue end
local model = v.modelEnt
local sprite = v.spriteMaterial
if (!v.bone) then continue end
local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )
if (!pos) then continue end
if (v.type == "Model" and IsValid(model)) then
model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
ang:RotateAroundAxis(ang:Up(), v.angle.y)
ang:RotateAroundAxis(ang:Right(), v.angle.p)
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
model:SetAngles(ang)
--model:SetModelScale(v.size)
local matrix = Matrix()
matrix:Scale(v.size)
model:EnableMatrix( "RenderMultiply", matrix )
if (v.material == "") then
model:SetMaterial("")
elseif (model:GetMaterial() != v.material) then
model:SetMaterial( v.material )
end
if IsValid(PLUGIN.updates) and PLUGIN.updates:IsVisible() then
model:SetSkin(3)
elseif IsValid(PLUGIN.viewLogs) and PLUGIN.viewLogs:IsVisible() then
model:SetSkin(5)
elseif IsValid(PLUGIN.viewLog) and PLUGIN.viewLog:IsVisible() then
model:SetSkin(6)
elseif IsValid(PLUGIN.editupdates) and PLUGIN.editupdates:IsVisible() then
model:SetSkin(7)
elseif (IsValid(PLUGIN.editUpdate) and PLUGIN.editUpdate:IsVisible()) or (IsValid(PLUGIN.newUpdate) and PLUGIN.newUpdate:IsVisible()) then
model:SetSkin(10)
elseif IsValid(PLUGIN.verdictCodes) and PLUGIN.verdictCodes:IsVisible() then
model:SetSkin(11)
elseif IsValid(PLUGIN.communicationCodes) and PLUGIN.communicationCodes:IsVisible() then
model:SetSkin(12)
elseif IsValid(PLUGIN.datafileInfo) and PLUGIN.datafileInfo:IsVisible() then
model:SetSkin(4)
elseif IsValid(PLUGIN.viewEntryLogs) and PLUGIN.viewEntryLogs:IsVisible() then
model:SetSkin(13)
elseif IsValid(PLUGIN.violationsTitleSubframe) and PLUGIN.violationsTitleSubframe:IsVisible() then
model:SetSkin(16)
else
model:SetSkin(0)
end
if (v.bodygroup) then
for k, v1 in pairs( v.bodygroup ) do
if (model:GetBodygroup(k) != v1) then
model:SetBodygroup(k, v1)
end
end
end
if (v.surpresslightning) then
render.SuppressEngineLighting(true)
end
render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
render.SetBlend(v.color.a/255)
model:DrawModel()
render.SetBlend(1)
render.SetColorModulation(1, 1, 1)
if (v.surpresslightning) then
render.SuppressEngineLighting(false)
end
elseif (v.type == "Sprite" and sprite) then
local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
render.SetMaterial(sprite)
render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
elseif (v.type == "Quad" and v.draw_func) then
local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
ang:RotateAroundAxis(ang:Up(), v.angle.y)
ang:RotateAroundAxis(ang:Right(), v.angle.p)
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
cam.Start3D2D(drawpos, ang, v.size)
v.draw_func( self )
cam.End3D2D()
end
end
end
SWEP.wRenderOrder = nil
function SWEP:DrawWorldModel()
if (self.ShowWorldModel == nil or self.ShowWorldModel) then
self:DrawModel()
end
if (!self.WElements) then return end
if (!self.wRenderOrder) then
self.wRenderOrder = {}
for k, v in pairs( self.WElements ) do
if (v.type == "Model") then
table.insert(self.wRenderOrder, 1, k)
elseif (v.type == "Sprite" or v.type == "Quad") then
table.insert(self.wRenderOrder, k)
end
end
end
local bone_ent
if (IsValid(self.Owner)) then
bone_ent = self.Owner
else
-- when the weapon is dropped
bone_ent = self
end
for _, name in pairs( self.wRenderOrder ) do
local v = self.WElements[name]
if (!v) then self.wRenderOrder = nil break end
if (v.hide) then continue end
local pos, ang
if (v.bone) then
pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent )
else
pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" )
end
if (!pos) then continue end
local model = v.modelEnt
local sprite = v.spriteMaterial
if (v.type == "Model" and IsValid(model)) then
model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
ang:RotateAroundAxis(ang:Up(), v.angle.y)
ang:RotateAroundAxis(ang:Right(), v.angle.p)
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
model:SetAngles(ang)
--model:SetModelScale(v.size)
local matrix = Matrix()
matrix:Scale(v.size)
model:EnableMatrix( "RenderMultiply", matrix )
if (v.material == "") then
model:SetMaterial("")
elseif (model:GetMaterial() != v.material) then
model:SetMaterial( v.material )
end
if IsValid(PLUGIN.updates) and PLUGIN.updates:IsVisible() then
model:SetSkin(3)
elseif IsValid(PLUGIN.viewLogs) and PLUGIN.viewLogs:IsVisible() then
model:SetSkin(5)
elseif IsValid(PLUGIN.viewLog) and PLUGIN.viewLog:IsVisible() then
model:SetSkin(6)
elseif IsValid(PLUGIN.editupdates) and PLUGIN.editupdates:IsVisible() then
model:SetSkin(7)
elseif (IsValid(PLUGIN.editUpdate) and PLUGIN.editUpdate:IsVisible()) or (IsValid(PLUGIN.newUpdate) and PLUGIN.newUpdate:IsVisible()) then
model:SetSkin(10)
elseif IsValid(PLUGIN.verdictCodes) and PLUGIN.verdictCodes:IsVisible() then
model:SetSkin(11)
elseif IsValid(PLUGIN.communicationCodes) and PLUGIN.communicationCodes:IsVisible() then
model:SetSkin(12)
elseif IsValid(PLUGIN.datafileInfo) and PLUGIN.datafileInfo:IsVisible() then
model:SetSkin(4)
elseif IsValid(PLUGIN.viewEntryLogs) and PLUGIN.viewEntryLogs:IsVisible() then
model:SetSkin(13)
elseif IsValid(PLUGIN.violationsTitleSubframe) and PLUGIN.violationsTitleSubframe:IsVisible() then
model:SetSkin(16)
else
model:SetSkin(0)
end
if (v.bodygroup) then
for k, v1 in pairs( v.bodygroup ) do
if (model:GetBodygroup(k) != v1) then
model:SetBodygroup(k, v1)
end
end
end
if (v.surpresslightning) then
render.SuppressEngineLighting(true)
end
render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
render.SetBlend(v.color.a/255)
model:DrawModel()
render.SetBlend(1)
render.SetColorModulation(1, 1, 1)
if (v.surpresslightning) then
render.SuppressEngineLighting(false)
end
elseif (v.type == "Sprite" and sprite) then
local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
render.SetMaterial(sprite)
render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
elseif (v.type == "Quad" and v.draw_func) then
local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
ang:RotateAroundAxis(ang:Up(), v.angle.y)
ang:RotateAroundAxis(ang:Right(), v.angle.p)
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
cam.Start3D2D(drawpos, ang, v.size)
v.draw_func( self )
cam.End3D2D()
end
end
end
function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )
local bone, pos, ang
if (tab.rel and tab.rel != "") then
local v = basetab[tab.rel]
if (!v) then return end
pos, ang = self:GetBoneOrientation( basetab, v, ent )
if (!pos) then return end
pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
ang:RotateAroundAxis(ang:Up(), v.angle.y)
ang:RotateAroundAxis(ang:Right(), v.angle.p)
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
else
bone = ent:LookupBone(bone_override or tab.bone)
if (!bone) then return end
pos, ang = Vector(0,0,0), Angle(0,0,0)
local m = ent:GetBoneMatrix(bone)
if (m) then
pos, ang = m:GetTranslation(), m:GetAngles()
end
if (IsValid(self.Owner) and self.Owner:IsPlayer() and
ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
ang.r = -ang.r -- Fixes mirrored models
end
end
return pos, ang
end
function SWEP:CreateModels( tab )
if (!tab) then return end
for _, v in pairs( tab ) do
if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and
string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then
v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
if (IsValid(v.modelEnt)) then
v.modelEnt:SetPos(self:GetPos())
v.modelEnt:SetAngles(self:GetAngles())
v.modelEnt:SetParent(self)
v.modelEnt:SetNoDraw(true)
v.createdModel = v.model
else
v.modelEnt = nil
end
elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite)
and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then
local name = v.sprite.."-"
local params = { ["$basetexture"] = v.sprite }
-- make sure we create a unique name based on the selected options
local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
for _, j in pairs( tocheck ) do
if (v[j]) then
params["$"..j] = 1
name = name.."1"
else
name = name.."0"
end
end
v.createdSprite = v.sprite
v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)
end
end
end
local allbones
local hasGarryFixedBoneScalingYet = false
function SWEP:UpdateBonePositions(vm)
if self.ViewModelBoneMods then
if (!vm:GetBoneCount()) then return end
-- !! WORKAROUND !! --
-- We need to check all model names :/
local loopthrough = self.ViewModelBoneMods
if (!hasGarryFixedBoneScalingYet) then
allbones = {}
for i=0, vm:GetBoneCount() do
local bonename = vm:GetBoneName(i)
if (self.ViewModelBoneMods[bonename]) then
allbones[bonename] = self.ViewModelBoneMods[bonename]
else
allbones[bonename] = {
scale = Vector(1,1,1),
pos = Vector(0,0,0),
angle = Angle(0,0,0)
}
end
end
loopthrough = allbones
end
-- !! ----------- !! --
for k, v in pairs( loopthrough ) do
local bone = vm:LookupBone(k)
if (!bone) then continue end
-- !! WORKAROUND !! --
local s = Vector(v.scale.x,v.scale.y,v.scale.z)
local p = Vector(v.pos.x,v.pos.y,v.pos.z)
local ms = Vector(1,1,1)
if (!hasGarryFixedBoneScalingYet) then
local cur = vm:GetBoneParent(bone)
while(cur >= 0) do
local pscale = loopthrough[vm:GetBoneName(cur)].scale
ms = ms * pscale
cur = vm:GetBoneParent(cur)
end
end
s = s * ms
-- !! ----------- !! --
if vm:GetManipulateBoneScale(bone) != s then
vm:ManipulateBoneScale( bone, s )
end
if vm:GetManipulateBoneAngles(bone) != v.angle then
vm:ManipulateBoneAngles( bone, v.angle )
end
if vm:GetManipulateBonePosition(bone) != p then
vm:ManipulateBonePosition( bone, p )
end
end
else
self:ResetBonePositions(vm)
end
end
function SWEP:ResetBonePositions(vm)
if (!vm:GetBoneCount()) then return end
for i=0, vm:GetBoneCount() do
vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
end
end
--luacheck: ignore 122
function table.FullCopy( tab )
if (!tab) then return nil end
local res = {}
for k, v in pairs( tab ) do
if (type(v) == "table") then
res[k] = table.FullCopy(v)
elseif (type(v) == "Vector") then
res[k] = Vector(v.x, v.y, v.z)
elseif (type(v) == "Angle") then
res[k] = Angle(v.p, v.y, v.r)
else
res[k] = v
end
end
return res
end
end
----------------------------------------------------
function SWEP:OnRemove()
end
function SWEP:Deploy()
--if !IsValid(self.Owner.C4s) then self.Owner.C4s = {} end
self.Weapon:SendWeaponAnim(ACT_SLAM_TRIPMINE_DRAW)
end
function SWEP:PrimaryAttack()
self:EmitSound( "UI/buttonclick.wav" )
self:SetNextPrimaryFire( CurTime()+2 )
if SERVER and IsFirstTimePredicted() then
if (PLUGIN:HasAccessToDatafile(self.Owner)) then
PLUGIN:Refresh(self.Owner)
else
self.Owner:NotifyLocalized("You do not have access to the datapad")
end
end
end
function SWEP:SecondaryAttack()
end
function SWEP:Holster()
if CLIENT and IsValid(self.Owner) then
local vm = self.Owner:GetViewModel()
if IsValid(vm) then
self:ResetBonePositions(vm)
end
end
return true
end
function SWEP:OnRemove()
self:Holster()
end

View File

@@ -0,0 +1,61 @@
--[[
| 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
ITEM.name = "Komputer Obywatela"
ITEM.uniqueID = "cit_computer"
ITEM.model = "models/willardnetworks/props/willard_computer.mdl"
ITEM.width = 2
ITEM.height = 2
ITEM.description = "Komputer na którym między innymi można zapisywać notatki."
ITEM.category = "Technology"
ITEM.functions.Place = {
OnRun = function(itemTable)
local client = itemTable.player
local entity = ents.Create("ix_computer")
local trace = client:GetEyeTraceNoCursor()
if (trace.HitPos:Distance( client:GetShootPos() ) <= 192) and !client.CantPlace then
entity:SetPos(trace.HitPos + Vector( 0, 0, 17 ))
entity:Spawn()
entity:SetNWInt("owner", client:GetCharacter():GetID())
client.CantPlace = true
if itemTable:GetData("users") then
entity.users = itemTable:GetData("users")
end
if itemTable:GetData("notes") then
entity.notes = itemTable:GetData("notes")
end
if (IsValid(entity)) then
entity:SetAngles(Angle(0, client:EyeAngles().yaw + 180, 0))
end
ix.saveEnts:SaveEntity(entity)
timer.Simple(3, function()
if client then
client.CantPlace = false
end
end)
elseif client.CantPlace then
client:NotifyLocalized("Nie możesz tego tu postawić!")
return false
else
client:NotifyLocalized("Nie możesz postawić tego tak daleko!")
return false
end
end
}

View File

@@ -0,0 +1,69 @@
--[[
| 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
ITEM.name = "Dyskietka"
ITEM.model = "models/props/cs_office/computer_caseb_p9a.mdl"
ITEM.skin = 1
ITEM.width = 1
ITEM.height = 1
ITEM.description = "Dyskietka na której można przechowywać informacje."
ITEM.category = "Technology"
function ITEM:GetName()
if self:GetData("customName", false) then
return self:GetData("customName", false)
end
return self.name
end
ITEM.functions.Place = {
name = "Włóż do komputera",
tip = "equipTip",
icon = "icon16/link_add.png",
OnRun = function(itemTable)
if (SERVER) then
local client = itemTable.player
PLUGIN:InsertDisk(client, itemTable)
return false
end
end,
OnCanRun = function(itemTable)
if IsValid(itemTable.entity) then return false end
end
}
function ITEM:OnTransferred(curInv, inventory)
if (SERVER) then
if self.computer and IsValid(self.computer) then
self.computer.hasDiskInserted = nil
end
end
end
ITEM.functions.Name = {
name = "Nazwij dysk",
tip = "equipTip",
icon = "icon16/link_add.png",
OnRun = function(itemTable)
if (SERVER) then
local client = itemTable.player
if !client then return end
netstream.Start(client, "SetFloppyDiskName", itemTable:GetData("customName", false), itemTable.id, itemTable:GetData("password", false))
end
return false
end
}

View File

@@ -0,0 +1,62 @@
--[[
| 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
ITEM.name = "Komputer medyczny"
ITEM.uniqueID = "med_computer"
ITEM.model = "models/willardnetworks/props/willard_computer.mdl"
ITEM.skin = 1
ITEM.width = 2
ITEM.height = 2
ITEM.description = "Komputer, w którym można przeglądać raporty medyczne."
ITEM.category = "Technology"
ITEM.functions.Place = {
OnRun = function(itemTable)
local client = itemTable.player
local entity = ents.Create("ix_medical_computer")
local trace = client:GetEyeTraceNoCursor()
if (trace.HitPos:Distance( client:GetShootPos() ) <= 192) and !client.CantPlace then
entity:SetPos(trace.HitPos + Vector( 0, 0, 17 ))
entity:Spawn()
entity:SetNWInt("owner", client:GetCharacter():GetID())
client.CantPlace = true
if itemTable:GetData("users") then
entity.users = itemTable:GetData("users")
end
if itemTable:GetData("notes") then
entity.notes = itemTable:GetData("notes")
end
if (IsValid(entity)) then
entity:SetAngles(Angle(0, client:EyeAngles().yaw + 180, 0))
end
ix.saveEnts:SaveEntity(entity)
timer.Simple(3, function()
if client then
client.CantPlace = false
end
end)
elseif client.CantPlace then
client:NotifyLocalized("Nie możesz tego tu postawić!")
return false
else
client:NotifyLocalized("Nie możesz postawić tego tak daleko!")
return false
end
end
}

View File

@@ -0,0 +1,19 @@
--[[
| 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/
--]]
ITEM.name = "PDA Administracji Cywilnej"
ITEM.description = "PDA Administracji Cywilnej."
ITEM.model = "models/fruity/pda.mdl"
ITEM.class = "weapon_capda"
ITEM.weaponCategory = "pda"
ITEM.category = "Combine"
ITEM.width = 1
ITEM.height = 1
ITEM.KeepOnDeath = true

View File

@@ -0,0 +1,19 @@
--[[
| 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/
--]]
ITEM.name = "PDA Kombinatu"
ITEM.description = "PDA Kombinatu przeznaczony dla oficerów Civil Protection."
ITEM.model = "models/fruity/tablet/tablet_sfm.mdl"
ITEM.class = "weapon_datapad"
ITEM.weaponCategory = "pda"
ITEM.category = "Combine"
ITEM.width = 1
ITEM.height = 1
ITEM.KeepOnDeath = true

View File

@@ -0,0 +1,61 @@
--[[
| 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/
--]]
LANGUAGE = {
TeamName = "PT-%s",
TeamStatus = "PT-%s %s",
TeamMemberStatus = "CZŁONEK",
TeamOwnerStatus = "LIDER",
tabProtectionTeam = "Protection Team",
tabCreateTeam = "STWÓRZ PT",
tabJoinTeam = "DOŁĄCZ DO PT",
tabLeaveTeam = "OPUŚĆ PT",
TeamTransferOwner = "Przekaż dowodzenie",
TeamKickMember = "Wyrzuć członka",
TeamReassign = "Zmień indeks",
CannotUseTeamCommands = "Nie można używać komend PT!",
CannotPromoteTeamMembers = "Nie można promować członków PT!",
CannotKickTeamMembers = "Nie możesz wyrzucać członków PT!",
CannotReassignTeamIndex = "Nie możesz zmienić indeksu PT!",
NoCurrentTeam = "Nie jesteś członkiem PT!",
TargetNoCurrentTeam = "Osoba, którą próbujesz awansować, nie jest częścią PT!",
TargetNotSameTeam = "Osoba, którą próbujesz awansować, nie należy do tego samego PT!",
TeamMustClamp = "Musisz podać numer z przedziału 1-99!",
TeamMustLeave = "Musisz opuścić obecny PT przed dołączeniem do nowego!",
TeamAlreadyHasOwner = "Jest już lider PT!",
TeamAlreadyExists = "PT z indeksem '%s' już istnieje!",
TeamNonExistent = "PT '%s' nie istnieje!",
AlreadyHasTeam = "Jesteś już członkiem PT!",
KickedFromTeam = "Wyrzucono %s z PT.",
TeamCreated = "PT '%s' został pomyślnie utworzony.",
TeamReassigned = "PT '%s' został pomyślnie zmieniony na '%s'.",
TeamOwnerSet = "Przypisano %s jako nowy lider PT.",
TeamOwnerAssume = "Przejąłeś dowodzenie nad PT.",
JoinedTeam = "Pomyślnie dołączono do PT '%s'.",
LeftTeam = "Pomyślnie opuszczono PT '%s'.",
cmdCreatePTDesc = "Wprowadź numer indeksu dla nowego Protection Team. (1-99)",
cmdReassignPTDesc = "Wprowadź nowy numer indeksu dla bieżącego Squadu. (1-99)",
cmdPTCreate = "Stwórz Protection Team.",
cmdPTLeave = "Upuść swój Protection Team.",
cmdPTLead = "Awansuj członka PT na lidera PT lub przejmij pozycję lidera.",
cmdPTKick = "Wyrzuć członka PT.",
cmdPTReassign = "Zmień numer indeksu PT.",
cmdPTJoin = "Dołącz do Protection Team."
}

View File

@@ -0,0 +1,61 @@
--[[
| 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/
--]]
LANGUAGE = {
TeamName = "PT-%s",
TeamStatus = "PT-%s %s",
TeamMemberStatus = "CZŁONEK",
TeamOwnerStatus = "LIDER",
tabProtectionTeam = "Protection Team",
tabCreateTeam = "STWÓRZ PT",
tabJoinTeam = "DOŁĄCZ DO PT",
tabLeaveTeam = "OPUŚĆ PT",
TeamTransferOwner = "Przekaż dowodzenie",
TeamKickMember = "Wyrzuć członka",
TeamReassign = "Zmień indeks",
CannotUseTeamCommands = "Nie można używać komend PT!",
CannotPromoteTeamMembers = "Nie można promować członków PT!",
CannotKickTeamMembers = "Nie możesz wyrzucać członków PT!",
CannotReassignTeamIndex = "Nie możesz zmienić indeksu PT!",
NoCurrentTeam = "Nie jesteś członkiem PT!",
TargetNoCurrentTeam = "Osoba, którą próbujesz awansować, nie jest częścią PT!",
TargetNotSameTeam = "Osoba, którą próbujesz awansować, nie należy do tego samego PT!",
TeamMustClamp = "Musisz podać numer z przedziału 1-99!",
TeamMustLeave = "Musisz opuścić obecny PT przed dołączeniem do nowego!",
TeamAlreadyHasOwner = "Jest już lider PT!",
TeamAlreadyExists = "PT z indeksem '%s' już istnieje!",
TeamNonExistent = "PT '%s' nie istnieje!",
AlreadyHasTeam = "Jesteś już członkiem PT!",
KickedFromTeam = "Wyrzucono %s z PT.",
TeamCreated = "PT '%s' został pomyślnie utworzony.",
TeamReassigned = "PT '%s' został pomyślnie zmieniony na '%s'.",
TeamOwnerSet = "Przypisano %s jako nowy lider PT.",
TeamOwnerAssume = "Przejąłeś dowodzenie nad PT.",
JoinedTeam = "Pomyślnie dołączono do PT '%s'.",
LeftTeam = "Pomyślnie opuszczono PT '%s'.",
cmdCreatePTDesc = "Wprowadź numer indeksu dla nowego Protection Team. (1-99)",
cmdReassignPTDesc = "Wprowadź nowy numer indeksu dla bieżącego Squadu. (1-99)",
cmdPTCreate = "Stwórz Protection Team.",
cmdPTLeave = "Upuść swój Protection Team.",
cmdPTLead = "Awansuj członka PT na lidera PT lub przejmij pozycję lidera.",
cmdPTKick = "Wyrzuć członka PT.",
cmdPTReassign = "Zmień numer indeksu PT.",
cmdPTJoin = "Dołącz do Protection Team."
}

View File

@@ -0,0 +1,51 @@
--[[
| 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/
--]]
LANGUAGE = {
TeamOwnerStatus = "LÍDER",
tabProtectionTeam = "Equipo de Protección",
TeamMemberStatus = "MIEMBRO",
CannotUseTeamCommands = "¡No puedes usar comandos de EP!",
CannotReassignTeamIndex = "¡No puedes reasignar el índice del EP!",
tabJoinTeam = "UNIRSE A EP",
cmdCreatePTDesc = "Introduce el número de índice para tu Equipo de Protección. (1-99)",
TeamKickMember = "Expulsar Miembro",
NoCurrentTeam = "¡No eres parte de un EP!",
tabCreateTeam = "CREAR EQUIPO DE PROTECCIÓN",
TeamTransferOwner = "Transferir Liderazgo",
tabLeaveTeam = "SALIR DE UN EP",
CannotPromoteTeamMembers = "¡No puedes ascender a los miembros del EP!",
cmdReassignPTDesc = "Introduce un nuevo número de índice para tu Escuadrón actual. (1-99)",
CannotKickTeamMembers = "¡No puedes expulsar a miembros del EP!",
TeamMustClamp = "¡Debes introducir un número entre 1-99!",
TeamReassign = "Reasignar índice",
cmdPTCreate = "Crea un Equipo de Protección.",
cmdPTJoin = "Unirse a un Equipo de Protección.",
cmdPTLeave = "Salir de tu Equipo de Protección.",
AlreadyHasTeam = "¡Ya eres miembro de un EP!",
TeamOwnerSet = "El nuevo líder del EP se ha cambiado a %s.",
TeamNonExistent = "¡El EP '%s' no existe!",
LeftTeam = "Has salido con éxito del EP '%s'.",
TargetNotSameTeam = "¡La persona a la que intentas ascender no pertenece al mismo EP!",
TeamOwnerAssume = "Has asumido el liderazgo del EP.",
TeamReassigned = "EP '%s' reasignado con éxito a '%s'.",
JoinedTeam = "Incorporado con éxito al EP '%s'.",
cmdPTLead = "Ascender a un miembro del EP a líder del EP o asumir la posición de líder.",
TeamMustLeave = "¡Debes abandonar tu EP actual antes de entrar en uno nuevo!",
KickedFromTeam = "Has echado a %s del EP.",
cmdPTKick = "Expulsar a un miembro del EP.",
TargetNoCurrentTeam = "¡La persona que estás intentando ascender no es parte de un EP!",
TeamAlreadyHasOwner = "¡Ya hay un líder de EP!",
TeamAlreadyExists = "¡Un EP con índice '%s' ya existe!",
TeamCreated = "EP '%s' creado con éxito.",
TeamName = "EP-%s",
cmdPTReassign = "Reasignar índice numérico del EP.",
TeamStatus = "EP-%s %s"
}

View File

@@ -0,0 +1,55 @@
--[[
| 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/
--]]
ix.permits = ix.permits or {}
ix.permits.list = ix.permits.list or {}
function ix.permits.add(permit)
permit = string.utf8lower(permit)
ix.permits.list[permit] = true
end
function ix.permits.get()
return ix.permits.list or {}
end
function ix.permits.isEnded(validUntil)
if os.time() > validUntil then
return true
end
return false
end
do
local CHAR = ix.meta.character
function CHAR:HasPermit(permit)
permit = string.utf8lower(permit)
local permits = self:GetGenericdata().permits or {}
if (permits[permit]) and permits[permit] == true then
return true
end
if (isnumber(permits[permit])) and !ix.permits.isEnded(permits[permit]) then
return true
end
return false
end
function CHAR:GetPermits()
return self:GetGenericdata().permits
end
end

View File

@@ -0,0 +1,51 @@
--[[
| 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/
--]]
do
local CHAR = ix.meta.character
function CHAR:SetPermitUnlimited(permit)
self:SetPermit(permit, true)
end
function CHAR:DisablePermit(permit)
self:SetPermit(permit, false)
end
function CHAR:SetPermit(permit, weeks)
-- If weeks is true then it would be unlimited
local endTimeStamp = !isbool(weeks) and (os.time() + 3600 * 24 * 7 * weeks) or true
permit = string.utf8lower(permit)
local genericdata = self:GetGenericdata()
if !genericdata.permits then
genericdata.permits = {}
end
if !istable(genericdata.permits) then
genericdata.permits = {}
end
if !weeks then
genericdata.permits[permit] = nil
else
genericdata.permits[permit] = endTimeStamp
end
if (!genericdata.permits[permit]) then
genericdata.permits[permit] = nil
end
self:SetGenericdata(genericdata)
end
end

View File

@@ -0,0 +1,44 @@
--[[
| 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
netstream.Hook("SetDatafileLoyaltyPoints", function(target, amount)
netstream.Start("SetDatafileLoyaltyPointsServer", target, amount)
end)
netstream.Hook("OpenDatafileCl", function(table)
if !PLUGIN.contentSubframe then return end
if !IsValid(PLUGIN.contentSubframe) then return end
PLUGIN.file = table
if !PLUGIN.file or PLUGIN.file and istable(PLUGIN.file) and !PLUGIN.file.genericdata then
if !PLUGIN.file then return end
if istable(PLUGIN.file) and PLUGIN.file["charID"] then
if CAMI.PlayerHasAccess(LocalPlayer(), "Helix - Basic Admin Commands") then
Derma_Query("Something went wrong with the datafile of this individual", "Do you want to reset the datafile of charID: "..PLUGIN.file["charID"].."?",
"Confirm Operation", function()
netstream.Start("ResetDatafileToDefault", PLUGIN.file["charID"])
end, "Cancel")
end
end
return
end
for _, v in pairs(PLUGIN.contentSubframe:GetChildren()) do
v:SetVisible(false)
end
PLUGIN.datafileInfo = vgui.Create("ixDatafileInfo", PLUGIN.contentSubframe)
PLUGIN.datafileFunctions = vgui.Create("ixDatafileFunctions", PLUGIN.contentSubframe)
end)

View File

@@ -0,0 +1,37 @@
--[[
| 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
function PLUGIN:LoadFonts(font, genericFont)
surface.CreateFont( "DatapadTitle", {
font = "Open Sans Bold", -- Use the font-name which is shown to you by your operating system Font Viewer, not the file name
extended = true,
size = SScaleMin(32 / 3),
weight = 550,
antialias = true,
} )
end
netstream.Hook("OpenPDA", function(table, text)
if IsValid(PLUGIN.ixDatapad) then
PLUGIN.ixDatapad:Remove()
end
PLUGIN.updatelist = table
PLUGIN.ixDatapad = vgui.Create("ixDatafilePDA")
surface.PlaySound("willardnetworks/datapad/open.wav")
if (text != nil) then
PLUGIN.functions:SetVisible(false)
PLUGIN.searchProfiles = vgui.Create("ixDatapadSearchProfiles", PLUGIN.contentSubframe)
PLUGIN.searchEntry:SetValue(text)
PLUGIN.searchButton:DoClick()
end
end)

View File

@@ -0,0 +1,31 @@
--[[
| 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 = {}
function PANEL:Init()
self:SetSize(ScrW(), ScrH())
ix.gui.medicalComputer = self:Add("MedicalComputerBase")
end
function PANEL:Think()
if !IsValid(ix.gui.medicalComputer) then
self:Remove()
end
if IsValid(ix.gui.medicalComputer.functionsPanel) then
if IsValid(ix.gui.medicalComputer.functionsPanel.medicalButton) then
ix.gui.medicalComputer.functionsPanel.medicalButton:Remove()
end
end
end
vgui.Register("CitizenComputer", PANEL, "EditablePanel")

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,136 @@
--[[
| 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.file = {}
ix.flag.Add("T", "Bypass PDA Transaction Logs.")
ix.config.Add("TransactionLogDaysDatafile", 14, "How many days to show transaction logs for.", nil, {
data = {min = 1, max = 31},
category = "Datafile"
})
ix.command.Add("SetDatafilePoints", {
description = "Set datafile loyalty points.",
adminOnly = true,
arguments = {
ix.type.character,
ix.type.number
},
OnRun = function(self, client, target, amount)
if (target) then
local genericData = target:GetGenericdata()
if genericData.socialCredits then
genericData.socialCredits = !genericData.combine and math.Clamp(amount, 0, 200) or amount
target:SetGenericdata(genericData)
target:Save()
end
client:NotifyLocalized("Set "..target.player:Name().."'s points to "..amount)
end
end
})
ix.command.Add("Datafile", {
description = "Open datafile as Overwatch or OTA.",
OnCheckAccess = function(self, client)
local faction = ix.faction.Get(client:Team())
if (faction.alwaysDatafile or client:GetCharacter():HasFlags("U")) then
return true
elseif (client:HasActiveCombineSuit() and client:GetCharacter():GetInventory():HasItem("pda")) then
return true
end
return false
end,
arguments = {
ix.type.string
},
OnRun = function(self, client, text)
if (self:OnCheckAccess(client)) then
PLUGIN:Refresh(client, text)
else
client:NotifyLocalized("Nie masz dostępu do datapadu")
end
end
})
ix.char.RegisterVar("genericdata", {
field = "genericdata",
fieldType = ix.type.text,
default = {},
bNoDisplay = true,
isLocal = true,
OnSet = function(self, value)
local client = self:GetPlayer()
if (IsValid(client)) then
self.vars.genericdata = value
net.Start("ixCharacterVarChanged")
net.WriteUInt(self:GetID(), 32)
net.WriteString("genericdata")
net.WriteType(self.vars.genericdata)
net.Send(client)
end
end,
OnGet = function(self, default)
local genericdata = self.vars.genericdata
return genericdata
end,
OnAdjust = function(self, client, data, value, newData)
newData.genericdata = value
end
})
ix.char.RegisterVar("datafilelogs", {
field = "datafilelogs",
fieldType = ix.type.text,
default = {},
bNoDisplay = true,
bNoNetworking = true,
})
ix.char.RegisterVar("datafileviolations", {
field = "datafileviolations",
fieldType = ix.type.text,
default = {},
bNoDisplay = true,
bNoNetworking = true,
})
ix.char.RegisterVar("datafilemedicalrecords", {
field = "datafilemedicalrecords",
fieldType = ix.type.text,
default = {},
bNoDisplay = true,
bNoNetworking = true,
})
ix.char.RegisterVar("datapadnotes", {
field = "datapadnotes",
fieldType = ix.type.text,
default = "",
bNoDisplay = true,
bNoNetworking = true,
OnSet = function(self, value)
self.vars.datapadnotes = value
end,
OnGet = function(self, default)
local datapadnotes = self.vars.datapadnotes
return datapadnotes
end,
OnAdjust = function(self, client, data, value, newData)
newData.datapadnotes = value
end
})

View File

@@ -0,0 +1,15 @@
--[[
| 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.updatelist = {}
ix.util.IncludeDir("ixhl2rp/plugins/combineutilities/pda/derma", true)

View File

@@ -0,0 +1,530 @@
--[[
| 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
local datafields = {"genericdata", "datafilelogs", "datafileviolations", "datafilemedicalrecords"}
function PLUGIN:SendFile(client, file)
timer.Simple(0.05, function()
netstream.Start(client, "OpenDatafileCl", file)
end)
end
-- Include new required data to datafiles of old characters
function PLUGIN:UpdateOldVortData(character, genericdata)
if (!character or !istable(genericdata)) then return end
genericdata.collarID = character:GetCollarID() or "N/A"
genericdata.cohesionPoints = genericdata.socialCredits or 0
genericdata.cohesionPointsDate = ix.config.Get("day").."/"..ix.config.Get("month").."/"..ix.config.Get("year")
genericdata.nulled = "NIEAKTYWNY"
genericdata.cid = "N/A"
genericdata.name = nil
if (character:HasFlags("N") or character:GetBackground() == "Kolaborator") then
genericdata.nulled = "AKTYWNY"
end
for _, v in pairs(character:GetInventory():GetItems()) do
if (table.HasValue({"Obroża Vortigaunta", "Obroża Vortigaunta (fałszywa)"}, v.name) and v:GetData("equip") == true) then
if (v:GetData("collarID", nil) and v:GetData("sterilizedCredits", nil)) then
genericdata.cohesionPoints = v:GetData("sterilizedCredits", 0)
end
end
end
character:SetGenericdata(genericdata)
character:Save()
character:GetPlayer():Notify("Nowy format został pomyślnie zastosowany dla twojego pliku danych.")
end
-- Search the collarID through the database
function PLUGIN:LookUpCollarID(client, id, bNotify)
if (!client or !id) then return end
id = string.sub(id, 2)
local query = mysql:Select("ix_characters")
query:Select("name")
query:Select("faction")
query:Select("id")
query:Select("collarID")
query:Select("background")
query:Where("collarID", id)
query:Where("schema", Schema and Schema.folder or "helix")
query:Callback(function(result)
if (!istable(result) or #result == 0) then
return
end
local resultFactionString = result[1].faction
if (resultFactionString != "vortigaunt") then
return
end
local dataSelect = mysql:Select("ix_characters_data")
dataSelect:Where("id", result[1].id)
dataSelect:WhereIn("key", datafields)
dataSelect:Callback(function(dataSelectResult)
if (!istable(dataSelectResult) or #dataSelectResult == 0) then
return
end
local file = {}
for _, v in ipairs(dataSelectResult) do
file[v.key] = util.JSONToTable(v.data or "")
file["charID"] = result[1].id
if (v.key == "genericdata") then
if file[v.key].name != result[1].name then
file[v.key].name = result[1].name
local updateQuery = mysql:Update("ix_characters_data")
updateQuery:Update("data", util.TableToJSON(file[v.key]) or "")
updateQuery:Where("id", result[1].id)
updateQuery:Where("key", "genericdata")
updateQuery:Execute()
end
end
end
if (bNotify) then
local author = client:IsDispatch() and "OVERWATCH" or (ix.faction.Get(client:Team()).idInspectionText or "Unit") .. " " .. string.upper(client:GetCombineTag())
ix.combineNotify:AddNotification("LOG:// " .. author .. " przeprowadza inspekcję tożsamości na " .. string.upper("zasobie biotycznym:") .. " #" .. result[1].collarID)
end
self:SendFile(client, file)
end)
dataSelect:Execute()
end)
query:Execute()
end
function PLUGIN:RefreshDatafile(client, id, bIsLocal, bCachedID, bNotify)
if !client then return end
if (client:Team() == FACTION_SERVERADMIN) then
bNotify = false
end
--If the player is trying to view his/her own datafile
if (bIsLocal) then
local character = client:GetCharacter()
local file = {}
file["genericdata"] = character:GetGenericdata()
file["datafileviolations"] = character:GetDatafileviolations()
file["datafilemedicalrecords"] = character:GetDatafilemedicalrecords()
file["datafilelogs"] = character:GetDatafilelogs()
file["charID"] = character:GetID()
if character:IsVortigaunt() and !file["genericdata"].cohesionPoints then
self:UpdateOldVortData(character, file["genericdata"])
end
self:SendFile(client, file)
return
end
local target = false
if (bCachedID) then
if isnumber(tonumber(id)) then
if ix.char.loaded[id] then
target = ix.char.loaded[id]
end
end
end
if !target then
-- Check for cached characters
if (tonumber(id) != nil and string.utf8len(tostring(id)) <= 5) then
-- id to cid comparison
for _, v in pairs(ix.char.loaded) do
local cid = v.GetCid and v:GetCid()
local genericdata = v:GetGenericdata()
if (v:IsVortigaunt() and v:GetCid() == id and genericdata.cid == "N/A") then return end
if (cid and id) then
if (tostring(cid) == id) then
target = v
break
end
end
end
elseif (id != nil and string.sub(id, 1, 1) == "!") then
id = string.sub(id, 2)
for _, v in pairs(ix.char.loaded) do
if (v:IsVortigaunt() and v:GetCollarID() == id) then
target = v
break
end
end
else
-- id to name comparison
for _, v in pairs(ix.char.loaded) do
local genericdata = v:GetGenericdata()
if string.find(v:GetName(), id) then
if (v:IsVortigaunt() and genericdata.cid == "N/A") then return end
target = v
break
end
end
end
end
-- Make sure further code isn't ran
if target then
local file = {}
file["genericdata"] = target:GetGenericdata()
file["datafileviolations"] = target:GetDatafileviolations()
file["datafilemedicalrecords"] = target:GetDatafilemedicalrecords()
file["datafilelogs"] = target:GetDatafilelogs()
file["charID"] = target:GetID()
if (target:IsVortigaunt() and !file["genericdata"].cohesionPoints) then
self:UpdateOldVortData(target, file["genericdata"])
end
if (bNotify) then
local author = client:IsDispatch() and "OVERWATCH" or (ix.faction.Get(client:Team()).idInspectionText or "Unit") .. " " .. string.upper(client:GetCombineTag())
if (target:IsVortigaunt()) then
if (file["genericdata"].cid == "N/A" and file["genericdata"].collarID != "N/A") then
ix.combineNotify:AddNotification("LOG:// " .. author .. " performing identity inspection on " .. string.upper("biotic asset collar:") .. " #" .. target:GetCollarID())
elseif (file["genericdata"].cid == "N/A" and file["genericdata"].collarID == "N/A") then
ix.combineNotify:AddNotification("LOG:// " .. author .. " performing identity inspection on " .. string.upper("biotic asset collar:") .. " #" .. target:GetFakeCollarID())
else
ix.combineNotify:AddNotification("LOG:// " .. author .. " przeprowadza inspekcję tożsamości na " .. string.upper("zasobie biotycznym o identyfikatorze:") .. " #" .. file["genericdata"].cid)
end
else
ix.combineNotify:AddNotification("LOG:// " .. author .. " przeprowadza inspekcję tożsamości na '" .. string.upper(target:GetName()) .. "', #" .. target:GetCid())
end
end
self:SendFile(client, file)
return
end
-- If no cached character, search in datafile
if (tonumber(id) != nil and string.utf8len( id ) <= 5) then
local query = mysql:Select("ix_characters")
query:Select("name")
query:Select("faction")
query:Select("id")
query:Select("cid")
query:Select("background")
query:Where("cid", id)
query:Where("schema", Schema and Schema.folder or "helix")
query:Callback(function(result)
if (!istable(result) or #result == 0) then
return
end
local resultFactionString = result[1].faction
if (resultFactionString == "overwatch" and client:Team() != FACTION_OVERWATCH) then
client:NotifyLocalized("Nie masz dostępu do tego pliku danych!")
return false
end
if (resultFactionString == "ota" or resultFactionString == "administrator" or resultFactionString == "guard") then
local character = client:GetCharacter()
if (client:Team() != FACTION_OVERWATCH and client:Team() != FACTION_OTA and character:GetClass() != FACTION_MCP and client:Team() != CLASS_CP_CMD and character:GetClass() != CLASS_CP_CPT and character:GetClass() != CLASS_CP_RL) then
if client:Team() != FACTION_ADMIN then
client:NotifyLocalized("Nie masz dostępu do tego pliku danych!")
return false
end
end
end
local dataSelect = mysql:Select("ix_characters_data")
dataSelect:Where("id", result[1].id)
dataSelect:WhereIn("key", datafields)
dataSelect:Callback(function(dataSelectResult)
if (!istable(dataSelectResult) or #dataSelectResult == 0) then
return
end
local file = {}
for _, v in ipairs(dataSelectResult) do
file[v.key] = util.JSONToTable(v.data or "")
file["charID"] = result[1].id
if (v.key == "genericdata") then
if (resultFactionString == "vortigaunt" and util.JSONToTable(v.data).cid == "N/A") then return end
if file[v.key].name != result[1].name then
file[v.key].name = result[1].name
local updateQuery = mysql:Update("ix_characters_data")
updateQuery:Update("data", util.TableToJSON(file[v.key]) or "")
updateQuery:Where("id", result[1].id)
updateQuery:Where("key", "genericdata")
updateQuery:Execute()
end
end
end
if (bNotify) then
local author = client:IsDispatch() and "OVERWATCH" or (ix.faction.Get(client:Team()).idInspectionText or "Unit") .. " " .. string.upper(client:GetCombineTag())
ix.combineNotify:AddNotification("LOG:// " .. author .. " przeprowadza inspekcję tożsamości na '" .. string.upper(result[1].name) .. "', #" .. result[1].cid)
end
self:SendFile(client, file)
end)
dataSelect:Execute()
end)
query:Execute()
else
if (string.sub(id, 1, 1) == "!") then
self:LookUpCollarID(client, id, bNotify)
end
local query = mysql:Select("ix_characters")
query:Select("id")
query:Select("name")
query:Select("faction")
query:Select("background")
query:Select("cid")
query:WhereLike("name", id)
query:Where("schema", Schema and Schema.folder or "helix")
query:Callback(function(result)
if (!istable(result) or #result == 0) then
return
end
local resultFactionString = result[1].faction
if (resultFactionString == "overwatch" and client:Team() != FACTION_OVERWATCH) then
client:NotifyLocalized("Nie masz dostępu do tego pliku danych!")
return false
end
if (resultFactionString == "ota" or resultFactionString == "administrator" or resultFactionString == "guard") then
local character = client:GetCharacter()
if (client:Team() != FACTION_OVERWATCH and client:Team() != FACTION_OTA and character:GetClass() != FACTION_MCP and client:Team() != CLASS_CP_CMD and character:GetClass() != CLASS_CP_CPT and character:GetClass() != CLASS_CP_RL) then
if client:Team() != FACTION_ADMIN then
client:NotifyLocalized("Nie masz dostępu do tego pliku danych!")
return false
end
end
end
local dataSelect = mysql:Select("ix_characters_data")
dataSelect:Where("id", result[1].id)
dataSelect:WhereIn("key", datafields)
dataSelect:Callback(function(dataSelectResult)
if (!istable(dataSelectResult) or #dataSelectResult == 0) then
return
end
local file = {}
for _, v in ipairs(dataSelectResult) do
file[v.key] = util.JSONToTable(v.data or "")
file["charID"] = result[1].id
if (v.key == "genericdata") then
if (resultFactionString == "vortigaunt" and util.JSONToTable(v.data).cid == "N/A") then return end
if file[v.key].name != result[1].name then
file[v.key].name = result[1].name
local updateQuery = mysql:Update("ix_characters_data")
updateQuery:Update("data", util.TableToJSON(file[v.key]) or "")
updateQuery:Where("id", result[1].id)
updateQuery:Where("key", "genericdata")
updateQuery:Execute()
end
end
end
if (bNotify) then
local author = client:IsDispatch() and "OVERWATCH" or (ix.faction.Get(client:Team()).idInspectionText or "Unit") .. " " .. string.upper(client:GetCombineTag())
ix.combineNotify:AddNotification("LOG:// " .. author .. " przeprowadza inspekcję tożsamości na '" .. string.upper(result[1].name) .. "', #" .. result[1].cid)
end
self:SendFile(client, file)
end)
dataSelect:Execute()
end)
query:Execute()
end
end
netstream.Hook("RequestCIDCreditsDatafile", function(client, cid)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
cid = Schema:ZeroNumber(cid, 5)
local housing = ix.plugin.list["housing"]
if !housing then return end
housing:LookUpCardItemIDByCID(tostring(cid), function(result)
local idCardID = result[1].idcard or false
if !result then return end
if !ix.item.instances[idCardID] then
ix.item.LoadItemByID(idCardID, false, function(item)
if !item then return end
local credits = item:GetData("credits", 0)
netstream.Start(client, "UpdateDatafileCredits", credits)
end)
else
local credits = ix.item.instances[idCardID]:GetData("credits", 0)
netstream.Start(client, "UpdateDatafileCredits", credits)
end
end)
end)
netstream.Hook("ixDatafileRequestTransactionLogs", function(client, cid)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
cid = Schema:ZeroNumber(cid, 5)
ix.plugin.list.cid:SelectTransactions(client, "cid", cid, ix.config.Get("TransactionLogDaysDatafile", 14), nil, function(result)
netstream.Start(client, "ixDatafileReplyTransactionLogs", result)
end)
end)
netstream.Hook("TerminalReportCrime", function(client, name, cid, text, activeTerminal)
if !text or !name or !cid then return false end
if string.len(text) <= 0 then client:Notify("Nie możesz wysłać pustego zgłoszenia.") return end
if cid != activeTerminal.activeCID then
return false
end
local timestamp = ix.date.GetFormatted("%d.%m.%Y")
local queryObj = mysql:Insert("ix_crimereports")
queryObj:Insert("message_poster", name)
queryObj:Insert("message_text", text)
queryObj:Insert("message_date", timestamp)
queryObj:Insert("message_cid", cid)
queryObj:Execute()
ix.combineNotify:AddImportantNotification("WRN:// Zgłoszenie złożone przez " .. name .. " #" .. cid, Color(0, 150, 255), client, activeTerminal:GetPos())
end)
function PLUGIN:GetCrimeReports(client, bArchived, bResolved, curCollect)
local query = mysql:Select("ix_crimereports")
query:Select("message_id")
query:Select("message_text")
query:Select("message_date")
query:Select("message_poster")
query:Select("message_cid")
query:Callback(function(result)
if (!istable(result) or #result == 0) then
return
end
local toSort = {}
for key, _ in pairs(result) do
local posterIsTable = string.find(result[key].message_poster, "{")
if posterIsTable then result[key].message_poster = util.JSONToTable(result[key].message_poster) end
if posterIsTable or (bArchived or bResolved) then
if bArchived and result[key].message_poster.archived then
toSort[#toSort + 1] = result[key]
continue
end
if bResolved and result[key].message_poster.resolved then
toSort[#toSort + 1] = result[key]
continue
end
continue
end
toSort[#toSort + 1] = result[key]
end
local toSend = {}
for i = curCollect, curCollect + 5 do
if toSort[i] then
toSend[#toSend + 1] = toSort[i]
end
end
netstream.Start(client, "ReplyCrimeReports", toSend)
end)
query:Execute()
end
netstream.Hook("GetCrimeReports", function(client, bArchived, bResolved, curCollect)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
PLUGIN:GetCrimeReports(client, bArchived, bResolved, curCollect)
end)
netstream.Hook("DeleteCrimeReport", function(client, key, bDatapad, lastUsedTab, curCollect)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
local queryObj = mysql:Delete("ix_crimereports")
queryObj:Where("message_id", key)
queryObj:Execute()
PLUGIN:GetCrimeReports(client, (lastUsedTab == "archived" and true or false), (lastUsedTab == "resolved" and true or false), curCollect)
end)
netstream.Hook("ResolveCrimeReport", function(client, key, poster, bUnResolve, lastUsedTab, curCollect)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("NTC:// Zgłoszenie o ID #" .. key .. " zostało uznane za " .. (bUnResolve and "nierozwiązane" or "rozwiązane") .. " przez " .. string.upper(author), Color(171, 222, 47))
local queryObj = mysql:Update("ix_crimereports")
queryObj:Where("message_id", key)
queryObj:Update("message_poster", util.TableToJSON({poster = (istable(poster) and poster.poster or poster), resolved = (!bUnResolve and true or false), archived = (istable(poster) and poster.archived or false)}))
queryObj:Execute()
PLUGIN:GetCrimeReports(client, (lastUsedTab == "archived" and true or false), (lastUsedTab == "resolved" and true or false), curCollect)
end)
netstream.Hook("ArchiveCrimeReport", function(client, key, poster, bUnArchive, lastUsedTab, curCollect)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("NTC:// Zgłoszenie o ID #" .. key .. (bUnArchive and " odarchiwizowano" or " zarchiwizowano") .. " przez " .. string.upper(author), Color(171, 222, 47))
local queryObj = mysql:Update("ix_crimereports")
queryObj:Where("message_id", key)
queryObj:Update("message_poster", util.TableToJSON({poster = (istable(poster) and poster.poster or poster), resolved = (istable(poster) and poster.resolved or false), archived = (!bUnArchive and true or false)}))
queryObj:Execute()
PLUGIN:GetCrimeReports(client, (lastUsedTab == "archived" and true or false), (lastUsedTab == "resolved" and true or false), curCollect)
end)
netstream.Hook("ResetDatafileToDefault", function(client, charID)
if !CAMI.PlayerHasAccess(client, "Helix - Basic Admin Commands") then return end
local character = ix.char.loaded[charID]
if !character then
client:NotifyLocalized("Właściciel postaci musi być online, aby reset zadziałał.")
return
end
local player = character:GetPlayer()
if !player then return end
PLUGIN:CreateDatafile(player)
end)

View File

@@ -0,0 +1,883 @@
--[[
| 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
function PLUGIN:DatabaseConnected()
local query = mysql:Create("ix_datapad")
query:Create("update_id", "INT(11) UNSIGNED NOT NULL AUTO_INCREMENT")
query:Create("update_text", "TEXT")
query:Create("update_date", "TEXT")
query:Create("update_poster", "TEXT")
query:PrimaryKey("update_id")
query:Execute()
query = mysql:Create("ix_comgroupmessages")
query:Create("message_id", "INT(11) UNSIGNED NOT NULL AUTO_INCREMENT")
query:Create("message_text", "TEXT")
query:Create("message_date", "TEXT")
query:Create("message_poster", "TEXT")
query:Create("message_groupid", "TEXT")
query:PrimaryKey("message_id")
query:Execute()
query = mysql:Create("ix_comgroupreplies")
query:Create("reply_id", "INT(11) UNSIGNED NOT NULL AUTO_INCREMENT")
query:Create("reply_text", "TEXT")
query:Create("reply_date", "TEXT")
query:Create("reply_poster", "TEXT")
query:Create("reply_parent", "TEXT")
query:Create("reply_groupid", "TEXT")
query:PrimaryKey("reply_id")
query:Execute()
query = mysql:Create("ix_camessaging")
query:Create("message_id", "INT(11) UNSIGNED NOT NULL AUTO_INCREMENT")
query:Create("message_text", "TEXT")
query:Create("message_date", "TEXT")
query:Create("message_poster", "TEXT")
query:Create("message_cid", "TEXT")
query:Create("message_reply", "TEXT")
query:PrimaryKey("message_id")
query:Execute()
query = mysql:Create("ix_crimereports")
query:Create("message_id", "INT(11) UNSIGNED NOT NULL AUTO_INCREMENT")
query:Create("message_text", "TEXT")
query:Create("message_date", "TEXT")
query:Create("message_poster", "TEXT")
query:Create("message_cid", "TEXT")
query:PrimaryKey("message_id")
query:Execute()
end
function PLUGIN:HasAccessToDatafile(client)
if !client or client and !IsValid(client) then return false end
local faction = ix.faction.Get(client:Team())
if (faction.alwaysDatafile or client:GetCharacter():HasFlags("U")) then
return true
elseif (client:HasActiveCombineSuit() or faction.allowDatafile) then
if (client:GetCharacter():GetInventory():HasItem("pda") or client:GetActiveWeapon():GetClass() == "weapon_datapad") then
return true
end
end
end
function PLUGIN:GetUpdates(client)
local query = mysql:Select("ix_datapad")
query:Select("update_id")
query:Select("update_text")
query:Select("update_date")
query:Select("update_poster")
query:Callback(function(result)
if (!istable(result)) then
return
end
if (!table.IsEmpty(PLUGIN.updatelist)) then
table.Empty(PLUGIN.updatelist)
end
PLUGIN.updatelist = result
end)
query:Execute()
self:GetActivePermits(client)
end
function PLUGIN:Refresh(client, text)
PLUGIN:GetUpdates(client)
timer.Simple(0.05, function()
netstream.Start(client, "OpenPDA", PLUGIN.updatelist, text)
end)
end
function PLUGIN:GetConsoleUpdates(client)
PLUGIN:GetUpdates(client)
end
function PLUGIN:CharacterVarChanged(character, key, oldValue, value)
local genericdata = character:GetGenericdata()
if (key == "name" and genericdata) then
genericdata.name = value
character:SetGenericdata(genericdata)
if (IsValid(character:GetPlayer())) then
character:Save()
end
end
end
netstream.Hook("ClearArchivedCrimeReports", function(client)
local character = client:GetCharacter()
if (!character:IsCombine()) then
return client:NotifyLocalized("Only combine can clear crime reports.")
elseif !client:IsCombineRankAbove("i1") then
return client:NotifyLocalized("Your rank must be above i1 to clear crime reports.")
end
local query = mysql:Select("ix_crimereports")
query:Select("message_id")
query:Select("message_text")
query:Select("message_date")
query:Select("message_poster")
query:Select("message_cid")
query:Callback(function(result)
if (!istable(result) or #result == 0) then
return
end
local newMessages = 0
local clearedMessages = 0
for _, v in pairs(result) do
local msgPoster = util.JSONToTable(v["message_poster"])
local isArchived = msgPoster["archived"]
if !isArchived then continue end
local date = v["message_date"]
local messageDay = date[1] != "0" and date[1] .. date[2] .. "d" or date[2] .. "d"
local messageMonth = date[4] != "0" and date[4] .. date[5] .. "m" or date[5] .. "m"
local messageYear = date[7] .. date[8] .. date[9] .. date[10] .. "y"
local totalMessageTime = ix.util.GetStringTime(messageDay .. messageMonth .. messageYear)
local currentDay = ix.date.GetFormatted("%d")[1] != "0" and ix.date.GetFormatted("%d")[1] .. ix.date.GetFormatted("%d")[2] .. "d" or ix.date.GetFormatted("%d")[2] .. "d"
local currentMonth = ix.date.GetFormatted("%m") != "0" and ix.date.GetFormatted("%m")[1] .. ix.date.GetFormatted("%m")[2] .. "m" or ix.date.GetFormatted("%m")[2] .. "m"
local currentYear = ix.date.GetFormatted("%Y") .. "y"
local currentTotalTime = ix.util.GetStringTime(currentDay .. currentMonth .. currentYear)
if (currentTotalTime - totalMessageTime) < (ix.config.Get("crimeReportArchiveTime", 1) * 604800) then
newMessages = newMessages + 1
continue
end
local queryObj = mysql:Delete("ix_crimereports")
queryObj:Where("message_id", v["message_id"])
queryObj:Execute()
clearedMessages = clearedMessages + 1
end
client:NotifyLocalized(clearedMessages > 0 and "Successfully cleared " .. clearedMessages .. " archived crime reports. " .. "There are " .. newMessages .. " new archived crime reports that can't be cleared yet." or newMessages and "All archived reports are not older than " .. ix.config.Get("crimeReportArchiveTime", 1) .. " week(s)" or "No archived crime reports found.")
end)
query:Execute()
end)
netstream.Hook("AddUpdate", function(client, text)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("LOG:// Pobieranie aktualizacji manifestu pliku danych Overwatch")
timer.Simple(1, function()
ix.combineNotify:AddNotification("NTC:// Nowy plik danych Aktualizacji został opublikowany przez " .. string.upper(author), Color(171, 222, 47))
end)
local timestamp = os.date( "%d.%m.%Y" )
local queryObj = mysql:Insert("ix_datapad")
queryObj:Insert("update_text", text)
queryObj:Insert("update_date", timestamp)
queryObj:Insert("update_poster", client:Name())
queryObj:Execute()
PLUGIN:Refresh(client)
end)
netstream.Hook("RemoveUpdate", function(client, id)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("LOG:// Pobieranie zaktualizowanego manifestu aktualizacji pliku danych Overwatch")
timer.Simple(1, function()
ix.combineNotify:AddNotification("NTC:// Plik danych Aktualizacji o ID #" .. id .. " został usunięty przez " .. string.upper(author), Color(171, 222, 47))
end)
local queryObj = mysql:Delete("ix_datapad")
queryObj:Where("update_id", id)
queryObj:Execute()
PLUGIN:Refresh(client)
end)
netstream.Hook("EditUpdate", function(client, id, newText)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("LOG:// Pobieranie zaktualizowanego manifestu aktualizacji pliku danych Overwatch")
timer.Simple(1, function()
ix.combineNotify:AddNotification("NTC:// Plik danych Aktualizacji o ID #" .. id .. " został zaaktualizowany przez " .. string.upper(author), Color(171, 222, 47))
end)
local queryObj = mysql:Update("ix_datapad")
queryObj:Where("update_id", id)
queryObj:Update("update_text", newText)
queryObj:Execute()
PLUGIN:Refresh(client)
end)
netstream.Hook("SetDatafileLoyaltyPointsServer", function(client, target, amount)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
local genericData = target:GetCharacter():GetGenericdata()
if (genericData.socialCredits) then
genericData.socialCredits = !genericData.combine and math.Clamp(amount, 0, 200) or amount
target:GetCharacter():SetGenericdata(genericData)
target:GetCharacter():Save()
end
end)
function PLUGIN:GetActiveShopPermits(client, appID)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
local dataSelect = mysql:Select("ix_apartments_"..game.GetMap())
dataSelect:Where("app_id", appID)
dataSelect:Callback(function(dataSelectResult)
if (!istable(dataSelectResult) or #dataSelectResult == 0) then
return
end
for _, v in ipairs(dataSelectResult) do
local data = util.JSONToTable(v.app_permits)
if data and !table.IsEmpty(data) then
netstream.Start(client, "CreateActiveShopPermitsDatapad", data)
end
end
end)
dataSelect:Execute()
end
function PLUGIN:GetActivePermits(client)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
local dataSelect = mysql:Select("ix_characters_data")
dataSelect:WhereIn("key", "genericdata")
dataSelect:Callback(function(dataSelectResult)
if (!istable(dataSelectResult) or #dataSelectResult == 0) then
return
end
local people = {}
for _, v in ipairs(dataSelectResult) do
local data = util.JSONToTable(v.data)
if data and data.permits and !table.IsEmpty(data.permits) then
for k2, v2 in pairs(data.permits) do
if isnumber(v2) and v2 <= os.time() then
data.permits[k2] = nil
end
end
if !table.IsEmpty(data.permits) then
people[v.id] = data
end
end
end
netstream.Start(client, "CreateActivePermitsDatapad", people)
end)
dataSelect:Execute()
end
netstream.Hook("GetActiveShopPermitsDatapad", function(client, appID)
PLUGIN:GetActiveShopPermits(client, appID)
end)
netstream.Hook("ToggleShopPermitDatapad", function(client, permit, bValue, appID)
local housing = ix.plugin.Get("housing")
if !housing then return end
if housing.apartments[appID].type != "shop" then return client:NotifyLocalized("To nie jest sklep!") end
housing.apartments[appID].permits[permit] = bValue
housing:UpdateApartment(appID)
housing:HandleShopPermitUpdate(appID, permit)
end)
netstream.Hook("GetActivePermitsDatapad", function(client)
PLUGIN:GetActivePermits(client)
end)
util.AddNetworkString("CreateActiveWagesDatapad")
function PLUGIN:GetActiveWages(client, curCollect)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
local dataSelect = mysql:Select("ix_characters_data")
dataSelect:WhereIn("key", "genericdata")
dataSelect:Limit(5)
dataSelect:Offset(curCollect)
dataSelect:Callback(function(dataSelectResult)
if (!istable(dataSelectResult) or #dataSelectResult == 0) then return end
local people = {}
local loyalists = {}
for _, v in ipairs(dataSelectResult) do
if !v.data then continue end
local data = util.JSONToTable(v.data)
if !data then continue end
local wages = data.wages and tonumber(data.wages)
if isnumber(wages) and wages > 0 then
people[v.id] = data
end
local socialCredits = data.socialCredits and tonumber(data.socialCredits)
local loyaltyStatus = data.loyaltyStatus and string.lower(data.loyaltyStatus)
if !data.socialCredits and !data.loyaltyStatus then continue end
if isnumber(socialCredits) and socialCredits >= 175 then
loyalists[v.id] = data
end
if isstring(loyaltyStatus) and loyaltyStatus != "brak" then
loyalists[v.id] = data
end
end
net.Start("CreateActiveWagesDatapad")
net.WriteTable(people)
net.WriteTable(loyalists)
net.Send(client)
end)
dataSelect:Execute()
end
netstream.Hook("GetActiveWagesDatapad", function(client, curCollect)
PLUGIN:GetActiveWages(client, curCollect)
end)
netstream.Hook("RemovePermitDatapad", function(client, genericdata, loggedAction)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
if (loggedAction != nil) then
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("NTC:// Dla podmiotu '" .. string.upper(genericdata.name or genericdata.collarID) .. "' " .. (loggedAction == "permit" and "plik danych Zezwolenia" or loggedAction and "Dopłata" or "Status Lojalności") .. " został cofnięty przez " .. string.upper(author), Color(171, 222, 47))
end
local cachedCharacter = ix.char.loaded[genericdata.id]
if (cachedCharacter) then
cachedCharacter:SetGenericdata(genericdata)
if (IsValid(cachedCharacter:GetPlayer())) then
cachedCharacter:Save()
return
end
end
local queryObj = mysql:Update("ix_characters_data")
queryObj:Where("id", genericdata.id)
queryObj:Where("key", "genericdata")
queryObj:Update("data", util.TableToJSON(genericdata))
queryObj:Execute()
end)
netstream.Hook("UpdateDatafileLogs", function(client, id, logs, key, subject)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
if (!client:IsCombineRankAbove("RL") and !client:GetCharacter():HasFlags("L")) then
client:Notify("Nie możesz usunąć tego logu, ponieważ nie masz wystarczająco wysokiej rangi lub nie nosisz mundur!")
return false
end
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("NTC:// Plik danych logu '" .. string.upper(subject) .. "' został usunięty przez " .. string.upper(author), Color(171, 222, 47))
local cachedCharacter = ix.char.loaded[id]
if (cachedCharacter) then
cachedCharacter:SetDatafilelogs(logs)
if (IsValid(cachedCharacter:GetPlayer())) then
cachedCharacter:Save()
return
end
end
local queryObj = mysql:Update("ix_characters_data")
queryObj:Where("id", id)
queryObj:Where("key", "datafilelogs")
queryObj:Update("data", util.TableToJSON(logs))
queryObj:Execute()
end)
netstream.Hook("UpdateDatafileMedical", function(client, id, logs, subject, isFromCMUPDA)
if (!PLUGIN:HasAccessToDatafile(client) and !isFromCMUPDA) then return end
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("NTC:// Plik danych wpisu 'MEDYCZNE' '" .. string.upper(subject) .. "' został usunięty przez " .. string.upper(author), Color(171, 222, 47))
local cachedCharacter = ix.char.loaded[id]
if (cachedCharacter) then
cachedCharacter:SetDatafilemedicalrecords(logs)
if (IsValid(cachedCharacter:GetPlayer())) then
cachedCharacter:Save()
return
end
end
local queryObj = mysql:Update("ix_characters_data")
queryObj:Where("id", id)
queryObj:Where("key", "datafilemedicalrecords")
queryObj:Update("data", util.TableToJSON(logs))
queryObj:Execute()
end)
netstream.Hook("UpdateDatafileViolations", function(client, id, logs, subject)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("NTC:// Plik danych wpisu 'WYROCZENIE' '" .. string.upper(subject) .. "' został usunięty przez " .. string.upper(author), Color(171, 222, 47))
local cachedCharacter = ix.char.loaded[id]
if (cachedCharacter) then
cachedCharacter:SetDatafileviolations(logs)
if (IsValid(cachedCharacter:GetPlayer())) then
cachedCharacter:Save()
return
end
end
local queryObj = mysql:Update("ix_characters_data")
queryObj:Where("id", id)
queryObj:Where("key", "datafileviolations")
queryObj:Update("data", util.TableToJSON(logs))
queryObj:Execute()
end)
netstream.Hook("DatafilePromoteDemote", function(client, id, name)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
local cachedCharacter = ix.char.loaded[id]
if (cachedCharacter) then
cachedCharacter:SetName(name)
if (IsValid(cachedCharacter:GetPlayer())) then
cachedCharacter:Save()
return
end
end
local queryObj = mysql:Update("ix_characters")
queryObj:Where("id", id)
queryObj:Update("name", name)
queryObj:Execute()
end)
function PLUGIN:CreateDatafile(client)
if (client:IsValid()) then
local character = client:GetCharacter()
local geneticAge = character:GetAge() or "N/A"
local geneticHeight = character:GetHeight() or "N/A"
local geneticEyecolor = character:GetEyeColor() or "N/A"
local standardCredits = 50
local designatedStatus = "N/A"
local anticitizen = false
if (string.utf8lower(character:GetBackground()) == "zwolennik") then
standardCredits = 60
elseif (string.utf8lower(character:GetBackground()) == "wyrzutek") then
standardCredits = 35
elseif (character:GetFaction() == FACTION_CP) then
standardCredits = 0
end
local genericData
if character:IsVortigaunt() then
genericData = {
id = character:GetID(),
cid = "N/A",
collarID = character:GetCollarID() or "N/A",
cohesionPoints = 0,
cohesionPointsDate = os.date("%d/%m/%Y"),
nulled = "NIEAKTYWNY",
geneticDesc = geneticAge .." | ".. geneticHeight,
occupation = "N/A",
occupationDate = os.date("%d/%m/%Y"),
designatedStatus = designatedStatus,
designatedStatusDate = os.date("%d/%m/%Y"),
permits = {},
bol = false,
anticitizen = anticitizen,
combine = false,
loyaltyStatus = "BRAK",
wages = 0,
bypassCommunion = false,
housing = false,
shop = false,
}
if character:GetBackground() == "Kolaborator" then
genericData.cid = character:GetCid()
end
else
genericData = {
id = character:GetID(),
name = character:GetName(),
cid = character:GetCid() or "N/A",
socialCredits = standardCredits,
socialCreditsDate = os.time(),
geneticDesc = geneticAge.." | "..geneticHeight.." | "..geneticEyecolor.." OCZY",
occupation = "N/A",
occupationDate = os.date("%d/%m/%Y"),
designatedStatus = designatedStatus,
designatedStatusDate = os.date("%d/%m/%Y"),
permits = {},
bol = false,
anticitizen = anticitizen,
combine = false,
loyaltyStatus = "BRAK",
wages = 0,
bypassCommunion = false,
housing = false,
shop = false,
}
end
if ix.faction.Get(client:Team()).isCombineFaction then
genericData.combine = true
end
if client:IsDispatch() then
genericData.combine = "overwatch"
end
local Timestamp = os.time()
local defaultLogs = {
[1] = {
text = "PRZENIESIONY DO DYSTRYKTU",
date = os.date( "%H:%M:%S - %d/%m/%Y" , Timestamp ),
poster = "Overwatch",
},
}
local defaultViolations = {}
local defaultMedicalRecords = {}
character:SetGenericdata(genericData)
character:SetDatafilelogs(defaultLogs)
character:SetDatafileviolations(defaultViolations)
character:SetDatafilemedicalrecords(defaultMedicalRecords)
character:SetHasDatafile(true)
character:Save()
end
end
netstream.Hook("OpenDatafile", function(client, id, bIsLocal)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
PLUGIN:RefreshDatafile(client, id, bIsLocal, nil, true)
end)
function PLUGIN:EditDatafile(client, genericdata, bBypass, bNoRefresh, action)
if (!bBypass and !PLUGIN:HasAccessToDatafile(client)) then return end
if (action) then
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("NTC:// Podmiot '" .. string.upper(genericdata.name or genericdata.collarID) .. "' " .. action .. " przez " .. string.upper(author), Color(171, 222, 47))
end
local cachedCharacter = ix.char.loaded[genericdata.id]
if (cachedCharacter) then
cachedCharacter:SetGenericdata(genericdata)
if (IsValid(cachedCharacter:GetPlayer())) then
cachedCharacter:Save()
if (!bNoRefresh) then
PLUGIN:RefreshDatafile(client, genericdata.id, nil, true)
end
return
end
end
local queryObj = mysql:Update("ix_characters_data")
queryObj:Where("id", genericdata.id)
queryObj:Where("key", "genericdata")
queryObj:Update("data", util.TableToJSON(genericdata))
queryObj:Execute()
if (!bNoRefresh) then
PLUGIN:RefreshDatafile(client, genericdata.cid, nil)
end
end
netstream.Hook("EditDatafile", function(client, genericdata, action)
PLUGIN:EditDatafile(client, genericdata, nil, nil, action)
end)
function PLUGIN:AddLog(client, logsTable, genericdata, posterName, points, text, bNoRefresh, bBypass, bGenericNote)
if (!bBypass and !PLUGIN:HasAccessToDatafile(client)) then return end
local Timestamp = os.time()
if (!bNoRefresh or bBypass) then
logsTable[#logsTable + 1] = {
text = text,
date = Timestamp,
points = points or nil,
poster = posterName
}
end
if (bGenericNote) then
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("NTC:// Plik danych wpisu 'UWAGA' '" .. string.upper(genericdata.name or genericdata.collarID) .. "' został dodany przez " .. string.upper(author), Color(171, 222, 47))
end
local cachedCharacter = ix.char.loaded[genericdata.id]
if (cachedCharacter) then
cachedCharacter:SetDatafilelogs(logsTable)
if (IsValid(cachedCharacter:GetPlayer())) then
cachedCharacter:Save()
if !bNoRefresh then
PLUGIN:RefreshDatafile(client, genericdata.id, nil, true)
end
return
end
end
local queryObj = mysql:Update("ix_characters_data")
queryObj:Where("id", genericdata.id)
queryObj:Where("key", "datafilelogs")
queryObj:Update("data", util.TableToJSON(logsTable))
queryObj:Execute()
if bNoRefresh then return end
PLUGIN:RefreshDatafile(client, genericdata.cid, nil)
end
netstream.Hook("AddLog", function(client, logsTable, genericdata, posterName, points, text, bNoRefresh, bGenericNote)
PLUGIN:AddLog(client, logsTable, genericdata, posterName, points, text, bNoRefresh, false, bGenericNote)
end)
netstream.Hook("AddViolation", function(client, violationsTable, genericdata, posterName, text, posterID)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
violationsTable[#violationsTable + 1] = {
text = text,
date = os.date("%d/%m/%Y"),
poster = posterName,
posterID = posterID
}
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("NTC:// Plik danych wpisu 'WYKROCZENIE' '" .. string.upper(genericdata.name or genericdata.collarID) .. "' został dodany przez " .. string.upper(author), Color(171, 222, 47))
local cachedCharacter = ix.char.loaded[genericdata.id]
if (cachedCharacter) then
cachedCharacter:SetDatafileviolations(violationsTable)
if (IsValid(cachedCharacter:GetPlayer())) then
cachedCharacter:Save()
PLUGIN:RefreshDatafile(client, genericdata.id, nil, true)
return
end
end
local queryObj = mysql:Update("ix_characters_data")
queryObj:Where("id", genericdata.id)
queryObj:Where("key", "datafileviolations")
queryObj:Update("data", util.TableToJSON(violationsTable))
queryObj:Execute()
PLUGIN:RefreshDatafile(client, genericdata.cid, nil)
end)
netstream.Hook("SetWagesDatafile", function(client, genericdata, wages)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
genericdata.wages = wages
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("NTC:// Dopłata '" .. string.upper(genericdata.name or genericdata.collarID) .. "' została zmieniona na " .. wages .. " przez " .. string.upper(author), Color(171, 222, 47))
local cachedCharacter = ix.char.loaded[genericdata.id]
if (cachedCharacter) then
cachedCharacter:SetGenericdata(genericdata)
if (IsValid(cachedCharacter:GetPlayer())) then
cachedCharacter:Save()
PLUGIN:RefreshDatafile(client, genericdata.id, nil, true)
return
end
end
local queryObj = mysql:Update("ix_characters_data")
queryObj:Where("id", genericdata.id)
queryObj:Where("key", "genericdata")
queryObj:Update("data", util.TableToJSON(genericdata))
queryObj:Execute()
PLUGIN:RefreshDatafile(client, genericdata.cid, nil)
end)
function PLUGIN:UpdateGenericData(genericdata)
local cachedCharacter = ix.char.loaded[genericdata.id]
if (cachedCharacter) then
cachedCharacter:SetGenericdata(genericdata)
if (IsValid(cachedCharacter:GetPlayer())) then
cachedCharacter:Save()
PLUGIN:RefreshDatafile(false, genericdata.id, nil, true)
return
end
end
local queryObj = mysql:Update("ix_characters_data")
queryObj:Where("id", genericdata.id)
queryObj:Where("key", "genericdata")
queryObj:Update("data", util.TableToJSON(genericdata))
queryObj:Execute()
end
netstream.Hook("SetLoyalistStatusDatafile", function(client, genericdata, status)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
genericdata.loyaltyStatus = status
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("NTC:// Status Lojalności '" .. string.upper(genericdata.name or genericdata.collarID) .. "' został zaktualizowany na '" .. status .. "' przez " .. string.upper(author), Color(171, 222, 47))
local cachedCharacter = ix.char.loaded[genericdata.id]
if (cachedCharacter) then
cachedCharacter:SetGenericdata(genericdata)
if (IsValid(cachedCharacter:GetPlayer())) then
cachedCharacter:Save()
PLUGIN:RefreshDatafile(client, genericdata.id, nil, true)
return
end
end
local queryObj = mysql:Update("ix_characters_data")
queryObj:Where("id", genericdata.id)
queryObj:Where("key", "genericdata")
queryObj:Update("data", util.TableToJSON(genericdata))
queryObj:Execute()
PLUGIN:RefreshDatafile(client, genericdata.cid, nil)
end)
netstream.Hook("SetBypassDatafile", function(client, genericdata, bBypass)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
genericdata.bypassCommunion = bBypass
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("NTC:// Dostęp do komunikatora '" .. string.upper(genericdata.name or genericdata.collarID) .. "' został " .. (bBypass and "włączony" or "wyłączony") .. " przez " .. string.upper(author), Color(171, 222, 47))
local cachedCharacter = ix.char.loaded[genericdata.id]
if (cachedCharacter) then
cachedCharacter:SetGenericdata(genericdata)
if (IsValid(cachedCharacter:GetPlayer())) then
cachedCharacter:Save()
PLUGIN:RefreshDatafile(client, genericdata.id, nil, true)
return
end
end
local queryObj = mysql:Update("ix_characters_data")
queryObj:Where("id", genericdata.id)
queryObj:Where("key", "genericdata")
queryObj:Update("data", util.TableToJSON(genericdata))
queryObj:Execute()
PLUGIN:RefreshDatafile(client, genericdata.cid, nil)
end)
netstream.Hook("AddMedicalRecord", function(client, medicalTable, genericdata, posterName, text, isFromCMUPDA)
if (!PLUGIN:HasAccessToDatafile(client) and !isFromCMUPDA) then return end
medicalTable[#medicalTable + 1] = {
text = text,
date = os.date("%d/%m/%Y"),
poster = posterName
}
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("NTC:// Plik danych wpisu 'MEDYCZNE' '" .. string.upper(genericdata.name or genericdata.collarID) .. "' został dodany przez " .. string.upper(author), Color(171, 222, 47))
local cachedCharacter = ix.char.loaded[genericdata.id]
if (cachedCharacter) then
cachedCharacter:SetDatafilemedicalrecords(medicalTable)
if (IsValid(cachedCharacter:GetPlayer())) then
cachedCharacter:Save()
PLUGIN:RefreshDatafile(client, genericdata.id, nil, true)
return
end
end
local queryObj = mysql:Update("ix_characters_data")
queryObj:Where("id", genericdata.id)
queryObj:Where("key", "datafilemedicalrecords")
queryObj:Update("data", util.TableToJSON(medicalTable))
queryObj:Execute()
PLUGIN:RefreshDatafile(client, genericdata.cid, nil)
end)
netstream.Hook("SetDatafilePermit", function(client, genericdata, permitsTable)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
genericdata.permits = permitsTable
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("NTC:// Plik danych zezwoleń '" .. string.upper(genericdata.name or genericdata.collarID) .. "' został zaktualizowany przez " .. string.upper(author), Color(171, 222, 47))
local cachedCharacter = ix.char.loaded[genericdata.id]
if (cachedCharacter) then
cachedCharacter:SetGenericdata(genericdata)
if (IsValid(cachedCharacter:GetPlayer())) then
cachedCharacter:Save()
return
end
end
local queryObj = mysql:Update("ix_characters_data")
queryObj:Where("id", genericdata.id)
queryObj:Where("key", "genericdata")
queryObj:Update("data", util.TableToJSON(genericdata))
queryObj:Execute()
end)
netstream.Hook("GetPersonalNotesDatapad", function(client)
if (!PLUGIN:HasAccessToDatafile(client)) then return end
local character = client:GetCharacter()
if !character then return end
local notes = character:GetDatapadnotes()
if !notes then return end
netstream.Start(client, "ReplyPersonalNotesDatapad", notes)
end)
netstream.Hook("SavePersonalNotesDatapad", function(client, value)
local character = client:GetCharacter()
if !character then return end
character:SetDatapadnotes(value)
client:Notify("Zapisano notatki osobiste.")
end)

View File

@@ -0,0 +1,256 @@
--[[
| 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 = "Combine Utilities"
PLUGIN.author = "Fruity, wowm0d"
PLUGIN.description = "Adds combine entities and visual stuff."
ix.util.IncludeDir("ixhl2rp/plugins/combineutilities/pda", true)
ix.util.IncludeDir("ixhl2rp/plugins/combineutilities/teams", true)
ix.util.IncludeDir("ixhl2rp/plugins/combineutilities/consoles", true)
ix.util.IncludeDir("ixhl2rp/plugins/combineutilities/workshifts", true)
ix.plugin.LoadEntities("ixhl2rp/plugins/combineutilities/workshifts/entities")
ix.util.Include("sv_groupmessaging.lua")
ix.util.Include("sv_plugin.lua")
ix.flag.Add("L", "Access to delete Datafile Logs.")
ix.lang.AddTable("english", {
cmdCharTogglePermit = "Daje lub usuwa zezwolenie postaci, (nie)pozwalając jej na korzystanie z menu handlu.",
togglePermit = "%s zezwolenie na handel dla %s.",
togglePermitTarget = "%s %s zezwolenie na handel.",
cmdMassReward = "Nadaj SK wielu jednostkom CP jednocześnie. Użyj 'all', aby dać wszystkim CP.\nWprowadź oddzieloną spacjami listę (częściowych) nazw, które zostaną nadane określonym jednostkom.",
cmdAmputate = "Zwiększa obrażenia wymierzone w osobę, na którą patrzysz.\nWzmocnienie działa tylko przez 60 sekund. Cel musi być związany lub znokautowany.\nJeśli cel zginie, administratorzy zostaną powiadomieni o PK celu.",
identityInspection = "%s %s przeprowadza inspekcję tożsamości na %s, #%s",
})
ix.lang.AddTable("spanish", {
cmdAmputate = "Aumenta tu daño contra la persona a la que estás mirando.\nEl aumento sólo es válido durante 60 segundos. El objetivo debe estar atado o inconsciente.\nSi el objetivo muere, se avisa a los administradores para que hagan PK al objetivo.",
cmdCharTogglePermit = "Da o quita el permiso de un personaje, (des)permitiéndole usar el menú de comercio.",
identityInspection = "%s %s realizando inspección de identidad en %s, #%s",
togglePermitTarget = "%s ha %s tu permiso de comercio.",
togglePermit = "Tienes %s permisos de comercio de tipo %s.",
cmdMassReward = "Dar CE a múltiples CPCs a la vez. Usa \"all\" para dar a todas las unidades de Protección Civil.\nIntroduce una lista separada por espacios de nombres (parciales) para dar a unidades específicas."
})
ix.lang.AddTable("polish", {
cmdCharTogglePermit = "Daje lub usuwa zezwolenie postaci, (nie)pozwalając jej na korzystanie z menu handlu.",
togglePermit = "%s zezwolenie na handel dla %s.",
togglePermitTarget = "%s %s zezwolenie na handel.",
cmdMassReward = "Nadaj SK wielu jednostkom CP jednocześnie. Użyj 'all', aby dać wszystkim CP.\nWprowadź oddzieloną spacjami listę (częściowych) nazw, które zostaną nadane określonym jednostkom.",
cmdAmputate = "Zwiększa obrażenia wymierzone w osobę, na którą patrzysz.\nWzmocnienie działa tylko przez 60 sekund. Cel musi być związany lub znokautowany.\nJeśli cel zginie, administratorzy zostaną powiadomieni o PK celu.",
identityInspection = "%s %s przeprowadza inspekcję tożsamości na %s, #%s",
})
ix.char.RegisterVar("hasDatafile", {
default = false,
field = "hasDatafile",
fieldType = ix.type.bool,
bNoDisplay = true,
bNoNetworking = true,
})
ix.config.Add("communionSCRequirement", 150, "Amount of SC needed to use the terminal communion.", nil, {
data = {min = 101, max = 720},
category = "Datafile"
})
ix.config.Add("maxWorkshiftSocialCredits", 15, "The max amount of social credits given at workshift.", nil, {
data = {min = 1, max = 20},
category = "Workshift"
})
ix.config.Add("datafileNoConnection", false, "Disable the datafile's connection to the OCIN network", nil, {
category = "Datafile"
})
ix.config.Add("crimeReportArchiveTime", 1, "The amount of weeks that crime reports must be older than to be automatically cleared via 'clear' button.", nil, {
data = {min = 1, max = 12},
category = "Datafile"
})
local classes = {
[CLASS_CP_CMD] = true,
[CLASS_CP_CPT] = true,
[CLASS_CP_RL] = true,
[CLASS_OVERSEER] = true,
[FACTION_MCP] = true
}
ix.command.Add("MassReward", {
description = "@cmdMassReward",
arguments = {
ix.type.number,
ix.type.text
},
OnCheckAccess = function(self, client)
local character = client:GetCharacter()
local name = client:Name()
if (client:Team() != FACTION_OVERWATCH and !classes[character:GetClass()] and !Schema:IsCombineRank(name, "i2") and !Schema:IsCombineRank(name, "i1")) then
return false
end
return true
end,
OnRun = function(self, client, sc, targets)
if (sc == 0) then
client:Notify("Wprowadź prawidłową ilość SK!")
return false
end
local given = {}
if (targets == "*" or targets == "all") then
for _, v in ipairs(player.GetAll()) do
if (v:Team() != FACTION_CP or v == client) then continue end
local char = v:GetCharacter()
if (!char) then continue end
given[#given + 1] = v:Name()
local genericdata = char:GetGenericdata()
if (genericdata) then
genericdata.socialCredits = (genericdata.socialCredits or 0) + sc
char:SetGenericdata(genericdata)
char:Save()
end
if (sc > 0) then
v:Notify("Otrzymałeś "..sc.." kredytów sterylizowanych.")
else
v:Notify("Straciłeś "..math.abs(sc).." kredytów sterylizowanych.")
end
end
else
targets = string.Explode(" ", targets)
for _, v in ipairs(player.GetAll()) do
if (v:Team() != FACTION_CP) then continue end
local name = string.utf8lower(v:Name())
for _, target in ipairs(targets) do
if (string.find(name, string.utf8lower(target), 1, true)) then
local char = v:GetCharacter()
given[#given + 1] = v:Name()
local genericdata = char:GetGenericdata()
if (genericdata) then
genericdata.socialCredits = (genericdata.socialCredits or 0) + sc
char:SetGenericdata(genericdata)
char:Save()
end
if (sc > 0) then
v:Notify("Otrzymałeś "..sc.." kredytów sterylizowanych.")
else
v:Notify("Straciłeś "..math.abs(sc).." kredytów sterylizowanych.")
end
break
end
end
end
end
if (sc > 0) then
client:ChatNotify("Przekazałeś "..sc.." sterylizowanych kredytów do: "..table.concat(given, ", "))
else
client:ChatNotify("Odebrałeś "..sc.." sterylizowanych kredytów od: "..table.concat(given, ", "))
end
end
})
ix.command.Add("Amputate", {
description = "@cmdAmputate",
arguments = {
bit.bor(ix.type.text, ix.type.optional)
},
OnCheckAccess = function(self, client)
return ix.faction.Get(client:Team()).isCombineFaction
end,
OnRun = function(self, client, reason)
local target = client:GetEyeTraceNoCursor().Entity
if (!IsValid(target) or !(target:IsPlayer() or target:GetClass() == "prop_ragdoll")) then
client:Notify("Musisz patrzeć na prawidłowy cel!")
return
end
local bIsRagdoll = target:GetClass() == "prop_ragdoll"
if (target:GetPos():DistToSqr(client:GetPos()) > 400 * 400) then
client:Notify("Twój cel jest zbyt daleko!")
return
end
if ((bIsRagdoll and !IsValid(target.ixPlayer)) or (!bIsRagdoll and !target:IsRestricted())) then
client:Notify("Cel musi być nieprzytomny lub związany!")
return
end
if (bIsRagdoll) then
target = target.ixPlayer
end
target.beingAmputated = client
target.beingAmputatedEnd = CurTime() + 60
target.beingAmputatedReason = reason
client:Notify("Cel został wyznaczony do amputacji. Wydaj werdykt!")
end
})
ix.command.Add("SetCombineDoor", {
description = "Ustaw drzwi jako Kombinatu i by ich nazwa wyświetlała się w PDA CAB.",
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
entity:SetNetVar("combineDoor", name)
entity.ixCombineDoor = name
client:NotifyLocalized("Ustawiono te drzwi jako Kombinatu.")
hook.Run("SaveDoorData")
end
end
})
function PLUGIN:CreateDiskNameRequest(currentName, itemID, password)
Derma_StringRequest("Ustaw nazwę dyskietki", "Ustaw nazwę dyskietki", currentName or "Dyskietka", function(text)
if (text == "") then return end
netstream.Start("SetFloppyDiskName", text, itemID, password)
end)
end
if (CLIENT) then
netstream.Hook("SetFloppyDiskName", function(currentName, itemID, password)
if password then
Derma_StringRequest("Ten dysk jest chroniony hasłem.", "Wprowadź go.", "", function(password2)
if (password2 == "") then return end
PLUGIN:CreateDiskNameRequest(currentName, itemID, password2)
end)
return
end
PLUGIN:CreateDiskNameRequest(currentName, itemID, false)
end)
end

View File

@@ -0,0 +1,35 @@
--[[
| 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/
--]]
netstream.Hook("AddGroupMessageComputer", function(client, message, groupID, name)
if client:GetCharacter():GetGroupID() != groupID then return false end
local timestamp = os.date( "%d.%m.%Y" )
local queryObj = mysql:Insert("ix_comgroupmessages")
queryObj:Insert("message_text", message)
queryObj:Insert("message_date", timestamp)
queryObj:Insert("message_poster", name)
queryObj:Insert("message_groupid", groupID)
queryObj:Execute()
end)
netstream.Hook("AddGroupReplyComputer", function(client, message, groupID, name, parent)
if client:GetCharacter():GetGroupID() != groupID then return false end
local timestamp = os.date( "%d.%m.%Y" )
local queryObj = mysql:Insert("ix_comgroupreplies")
queryObj:Insert("reply_text", message)
queryObj:Insert("reply_date", timestamp)
queryObj:Insert("reply_poster", name)
queryObj:Insert("reply_groupid", groupID)
queryObj:Insert("reply_parent", parent)
queryObj:Execute()
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
function PLUGIN:GetHookCallPriority(hook)
if (hook == "HandlePlayerDeath") then
return 1100
end
end
function PLUGIN:PlayerLoadedCharacter(client, character)
-- Datafile
local bHasDatafile = character:GetHasDatafile()
if (!bHasDatafile) then
PLUGIN:CreateDatafile(client)
end
-- Teams
if (client:IsCombine()) then
self:LeaveTeam(client)
net.Start("ixPTSync")
net.WriteBool(true)
net.WriteTable(self.teams)
net.Send(client)
else
if (client:GetNetVar("ProtectionTeam")) then
self:LeaveTeam(client)
end
net.Start("ixPTSync")
net.WriteBool(false)
net.Send(client)
end
end
function PLUGIN:PostCalculatePlayerDamage(victim, damage, hitgroup)
if (victim.beingAmputated and victim.beingAmputatedEnd > CurTime() and damage:GetAttacker() == victim.beingAmputated) then
damage:ScaleDamage(hitgroup == HITGROUP_HEAD and 10 or 5)
end
end
function PLUGIN:HandlePlayerDeath(victim, damage)
if (victim.beingAmputated and victim.beingAmputatedEnd > CurTime() and damage:GetAttacker() == victim.beingAmputated) then
for _, v in ipairs(player.GetAll()) do
if (CAMI.PlayerHasAccess(v, "Helix - Ban Character")) then
v:ChatNotify(victim.beingAmputated:Name().." has amputated "..victim:Name().." for: "..(victim.beingAmputatedReason or "no reason given"))
end
end
victim.beingAmputated:Notify("Verdict delivered!")
victim.beingAmputated = nil
victim.beingAmputatedEnd = nil
victim.beingAmputatedReason = nil
return true --Do not let medical plugin interfere and put player in bleedout
end
end
-- Entity related functions
function PLUGIN:PlayerButtonDown( client, key )
if (IsFirstTimePredicted() and key == KEY_LALT) then
local entity = client:GetEyeTraceNoCursor().Entity
if !IsValid(entity) then
return false
end
if !entity.canUse then
return false
end
if (client:GetShootPos():Distance(entity:GetPos()) > 100) then
return false
end
if entity:GetNWInt("owner") and client:GetCharacter():GetID() != entity:GetNWInt("owner") then
return false
end
if entity.hasDiskInserted then client:NotifyLocalized("This computer has a disk inserted!") return false end
if (entity:GetClass() == "ix_medical_computer" or entity:GetClass() == "ix_computer") then
local getUsers = entity.users
local getNotes = entity.notes
local activeClass = "med_computer"
if entity:GetClass() == "ix_computer" then
activeClass = "cit_computer"
end
local pos = entity:GetPos()
ix.item.Spawn(activeClass, pos + Vector( 0, 0, 2 ), function(item, entityCreated) item:SetData("users", getUsers) item:SetData("notes", getNotes) end, entity:GetAngles())
entity:Remove()
end
end
end
function PLUGIN:RegisterSaveEnts()
ix.saveEnts:RegisterEntity("ix_medical_computer", true, true, true, {
OnSave = function(entity, data) --OnSave
data.motion = false
data.users = entity.users
data.notes = entity.notes
data.owner = entity:GetNWInt("owner")
end,
OnRestore = function(entity, data)
entity.users = data.users
entity.notes = data.notes
entity:SetNWInt("owner", data.owner)
end
})
ix.saveEnts:RegisterEntity("ix_computer", true, true, true, {
OnSave = function(entity, data) --OnSave
data.motion = false
data.users = entity.users
data.notes = entity.notes
data.owner = entity:GetNWInt("owner")
end,
OnRestore = function(entity, data)
entity.users = data.users
entity.notes = data.notes
entity:SetNWInt("owner", data.owner)
end
})
ix.saveEnts:RegisterEntity("ix_terminal", true, true, true, {
OnSave = function(entity, data) --OnSave
return {pos = data.pos, angles = data.angles, motion = false}
end,
})
ix.saveEnts:RegisterEntity("ix_console", true, true, true, {
OnSave = function(entity, data) --OnSave
return {pos = data.pos, angles = data.angles, motion = false}
end,
})
ix.saveEnts:RegisterEntity("npc_combine_camera", true, true, true, {
OnSave = function(entity, data) --OnSave
return {pos = data.pos, angles = data.angles, motion = false}
end,
OnRestore = function(entity, data)
entity:SetOwner(nil)
end,
})
ix.saveEnts:RegisterEntity("ix_workshiftterminal", true, true, true, {
OnSave = function(entity, data) --OnSave
return {pos = data.pos, angles = data.angles, motion = false}
end,
})
end
function PLUGIN:CanInsertDisk(client, item)
if !client then return false end
if !client:Alive() then return false end
local targetEnt = client:GetEyeTraceNoCursor().Entity
if !targetEnt then client:Notify("You are not looking at a computer!") return false end
if !IsValid(targetEnt) then client:Notify("You are not looking at a computer!") return false end
local entClass = targetEnt:GetClass()
if (entClass != "ix_medical_computer" and entClass != "ix_computer") then client:Notify("You are not looking at a computer!") return false end
if targetEnt.hasDiskInserted then client:Notify("There is already a disk in this computer!") return false end
return targetEnt
end
function PLUGIN:InsertDisk(client, item)
local computerEnt = self:CanInsertDisk(client, item)
if !computerEnt or (computerEnt and !IsValid(computerEnt)) then return false end
local bSuccess, error = item:Transfer(nil, nil, nil, item.player)
if (!bSuccess and isstring(error)) then
client:Notify("Could not drop the disk and insert it.")
return
end
local disk = bSuccess
local rotation = Vector(0, 0, 0)
local angle = computerEnt:GetAngles()
angle:RotateAroundAxis(angle:Up(), rotation.x)
disk:SetAngles(angle)
disk:SetPos(computerEnt:GetPos() + computerEnt:GetUp() * -1.5 + computerEnt:GetForward() * -15)
constraint.Weld( disk, computerEnt, 0, 0, 0, true, false )
local physObj = disk:GetPhysicsObject()
if !physObj then return end
physObj:EnableMotion(false)
computerEnt.hasDiskInserted = item:GetID()
item.computer = computerEnt
end
netstream.Hook("RequestFloppyDiskData", function(client, computerEnt, password)
if !computerEnt then return false end
if !IsValid(computerEnt) then return false end
if !IsEntity(computerEnt) then return false end
local diskItem = ix.item.instances[computerEnt.hasDiskInserted]
if !diskItem then return false end
local diskPassword = diskItem:GetData("password", false)
local diskData = diskItem:GetData("content", false)
if !diskPassword then
netstream.Start(client, "ReplyFloppyDiskData", true, false, diskData)
return
end
if (diskPassword and !password) or !password then
netstream.Start(client, "ReplyFloppyDiskData", false)
return
end
if (diskPassword != password) then
netstream.Start(client, "ReplyFloppyDiskData", false, true)
return
end
if (diskPassword == password) then
netstream.Start(client, "ReplyFloppyDiskData", true, false, diskData)
return
end
end)
netstream.Hook("FloppyDiskSetPassword", function(client, newPass, computerEnt)
if !computerEnt then return false end
if !IsValid(computerEnt) then return false end
if !IsEntity(computerEnt) then return false end
local diskItem = ix.item.instances[computerEnt.hasDiskInserted]
if !diskItem then return false end
diskItem:SetData("password", newPass)
end)
netstream.Hook("FloppyDiskSetData", function(client, newContent, computerEnt)
if !computerEnt then return false end
if !IsValid(computerEnt) then return false end
if !IsEntity(computerEnt) then return false end
local diskItem = ix.item.instances[computerEnt.hasDiskInserted]
if !diskItem then return false end
diskItem:SetData("content", newContent)
end)
netstream.Hook("SetFloppyDiskName", function(client, text, itemID, password)
local character = client:GetCharacter()
if !character then return false end
local inventory = character:GetInventory()
if !inventory then return false end
local item = ix.item.instances[itemID]
if !item then return end
local password2 = item:GetData("password", false)
if password2 and !password then return end
if password2 != password then
client:NotifyLocalized("Wrong password.")
return
end
if !inventory.GetItemByID then return false end
if !inventory:GetItemByID(itemID) then
local targetEnt = client:GetEyeTraceNoCursor().Entity
if !IsValid(targetEnt) then return false end
if targetEnt:GetClass() != "ix_item" then return false end
if (targetEnt.ixItemID and targetEnt.ixItemID != itemID) then return false end
end
item:SetData("customName", Schema:FirstToUpper(text))
client:NotifyLocalized("Set the disk name to "..Schema:FirstToUpper(text))
end)
netstream.Hook("FindLetterRecepient", function(client, text, itemID)
local character = client:GetCharacter()
if !character then return end
local inventory = character:GetInventory()
if !inventory then return end
if !inventory:GetItemByID(itemID) then return end
if inventory:GetItemByID(itemID).name != "Paper" then return end
if string.len(text) == 5 and isnumber(tonumber(text)) then
text = Schema:ZeroNumber(tonumber(text), 5)
end
local id = false
local name = false
local cid = false
for _, v in pairs(ix.char.loaded) do
if !isnumber(text) and string.len(tostring(text)) != 5 then
if (ix.util.StringMatches(v:GetName(), text)) then
id = v:GetID()
name = v:GetName()
cid = v:GetCid()
break
end
else
if ix.util.StringMatches(tostring(v:GetCid()), tostring(text)) then
id = v:GetID()
name = v:GetName()
cid = v:GetCid()
break
end
end
end
if !id or !name or !cid then
local receiverQuery = mysql:Select("ix_characters")
receiverQuery:Select("id")
receiverQuery:Select("name")
receiverQuery:Select("cid")
if !isnumber(text) and string.len(tostring(text)) != 5 then
receiverQuery:WhereLike("name", text)
else
receiverQuery:WhereLike("cid", text)
end
receiverQuery:Callback(function(result)
if (!result or !istable(result) or #result == 0) then
return
end
local first = result[1]
id = first.id
name = first.name
cid = first.cid
end)
receiverQuery:Execute()
end
timer.Simple(3, function()
if !id or !name or !cid then client:Notify("Could not find the person you were trying to send a letter to.") return end
cid = cid or "00000"
netstream.Start(client, "ReplyLetterRecepient", id, name, cid, itemID)
end)
end)
function PLUGIN:AddLogToDatafile(client, toCharID, fromCID, fromName)
local whomData = {
fromGenericData = false,
fromLogsTable = false,
toGenericData = false,
toLogsTable = false
}
for _, v in pairs(ix.char.loaded) do
if ix.util.StringMatches(tostring(v:GetCid()), tostring(fromCID)) then
whomData.fromGenericData = v:GetGenericdata()
whomData.fromLogsTable = v:GetDatafilelogs()
break
end
end
if ix.char.loaded[tonumber(toCharID)] then
whomData.toGenericData = ix.char.loaded[tonumber(toCharID)]:GetGenericdata()
whomData.toLogsTable = ix.char.loaded[tonumber(toCharID)]:GetDatafilelogs()
end
local addLogsTo = {["to"] = toCharID, ["from"] = fromCID}
if whomData.fromGenericData and whomData.fromLogsTable then addLogsTo["from"] = nil end
if whomData.toGenericData and whomData.toLogsTable then addLogsTo["to"] = nil end
if !whomData.fromGenericData or !whomData.fromLogsTable or !whomData.toGenericData or !whomData.toLogsTable then
for whom, id in pairs(addLogsTo) do
local query = mysql:Select("ix_characters")
query:Select("name")
query:Select("faction")
query:Select("id")
query:Select("cid")
if whom != "to" then
query:Where("cid", id)
else
query:Where("id", id)
end
query:Where("schema", Schema and Schema.folder or "helix")
query:Callback(function(result)
if (!istable(result) or #result == 0) then
return
end
local dataSelect = mysql:Select("ix_characters_data")
dataSelect:Where("id", result[1].id)
dataSelect:WhereIn("key", {"genericdata", "datafilelogs"})
dataSelect:Callback(function(dataSelectResult)
if (!istable(dataSelectResult) or #dataSelectResult == 0) then
return
end
for _, v in ipairs(dataSelectResult) do
if whom == "to" then
if v.key == "genericdata" then
whomData.toGenericData = util.JSONToTable(v.data or "")
elseif v.key == "datafilelogs" then
whomData.toLogsTable = util.JSONToTable(v.data or "")
end
else
if v.key == "genericdata" then
whomData.fromGenericData = util.JSONToTable(v.data or "")
elseif v.key == "datafilelogs" then
whomData.fromLogsTable = util.JSONToTable(v.data or "")
end
end
end
end)
dataSelect:Execute()
end)
query:Execute()
end
end
timer.Simple(4, function()
if whomData.fromGenericData and whomData.fromLogsTable and whomData.toGenericData and whomData.toLogsTable then
local combineutilities = ix.plugin.list["combineutilities"]
if combineutilities and combineutilities.AddLog then
for i = 1, 2 do
local logsT = (i == 1 and whomData.fromLogsTable or whomData.toLogsTable)
local genericT = (i == 1 and whomData.fromGenericData or whomData.toGenericData)
local fromName1 = whomData.fromGenericData.name or ""
local fromCID1 = whomData.fromGenericData.cid or ""
local toName = whomData.toGenericData.name or ""
local toCID = whomData.toGenericData.cid or ""
if (i == 1) then -- Only need the notification once
ix.combineNotify:AddNotification("LOG:// Subject '" .. fromName1 .. "' sent a letter to '" .. toName .. "'", nil, client)
end
combineutilities:AddLog(client, logsT, genericT, "TERMINAL", nil, "LETTER SENT/RECEIVED - "..fromName1.." | "..fromCID1.." -> "..toName.." | "..toCID, true, true)
end
end
end
end)
end
netstream.Hook("SendLetterToID", function(client, charID, itemID, fromCID, fromName)
local character = client:GetCharacter()
if !character then return end
local inventory = character:GetInventory()
if !inventory then return end
if !inventory:GetItemByID(itemID) then return end
if inventory:GetItemByID(itemID).name != "Paper" then return end
local paperInstance = ix.item.instances[tonumber(itemID)]
if !paperInstance then return end
local paperWritingID = paperInstance:GetData("writingID")
if !paperWritingID then return end
local paperTitle = paperInstance:GetData("title", "Paper")
local currentOwner = paperInstance:GetData("owner", false)
if ix.char.loaded[tonumber(charID)] then
ix.char.loaded[tonumber(charID)]:SetPurchasedItems("letter_"..itemID, {title = paperTitle, fromCID = fromCID, fromName = fromName, writingID = paperWritingID, owner = currentOwner})
client:Notify("Letter has been successfully sent.")
PLUGIN:AddLogToDatafile(client, charID, fromCID, fromName)
ix.item.instances[tonumber(itemID)]:Remove()
else
local dataSelect = mysql:Select("ix_characters_data")
dataSelect:Where("id", tonumber(charID))
dataSelect:WhereIn("key", "purchasedItems")
dataSelect:Callback(function(dataSelectResult)
if (!istable(dataSelectResult) or #dataSelectResult == 0) then
return
end
local purchasedItems = util.JSONToTable(dataSelectResult[1].data)
if !purchasedItems then return end
purchasedItems["letter_"..itemID] = {title = paperTitle, fromCID = fromCID, fromName = fromName, writingID = paperWritingID, owner = currentOwner}
local updateQuery = mysql:Update("ix_characters_data")
updateQuery:Update("data", util.TableToJSON(purchasedItems))
updateQuery:Where("id", tonumber(charID))
updateQuery:Where("key", "purchasedItems")
updateQuery:Execute()
ix.item.instances[tonumber(itemID)]:Remove()
PLUGIN:AddLogToDatafile(client, charID, fromCID, fromName)
end)
dataSelect:Execute()
client:Notify("Letter has been successfully sent.")
end
end)

View File

@@ -0,0 +1,167 @@
--[[
| 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
function PLUGIN:UpdateTeamMenu()
if (IsValid(ix.gui.protectionTeams)) then
ix.gui.protectionTeams.memberScroll:Clear()
ix.gui.protectionTeams.teamScroll:Clear()
if ix.gui.protectionTeams.leaveButton then
ix.gui.protectionTeams.leaveButton:Remove()
end
if ix.gui.protectionTeams.createButton then
ix.gui.protectionTeams.createButton:Remove()
end
if ix.gui.protectionTeams.joinButton then
ix.gui.protectionTeams.joinButton:Remove()
end
ix.gui.protectionTeams.CreateButtons()
end
end
function PLUGIN:CreateTeam(client, index)
self.teams[index] = {
owner = client,
members = {client}
}
hook.Run("OnCreateTeam", client, index)
end
function PLUGIN:ReassignTeam(index, newIndex)
local curTeam = self.teams[index]
self:DeleteTeam(index)
self:CreateTeam(curTeam["owner"], newIndex)
self.teams[newIndex]["members"] = curTeam["members"]
hook.Run("OnReassignTeam", index, newIndex)
end
function PLUGIN:DeleteTeam(index)
self.teams[index] = nil
hook.Run("OnDeleteTeam", index)
end
function PLUGIN:LeaveTeam(client, index)
if table.HasValue(self.teams[index]["members"], client) then
table.RemoveByValue(self.teams[index]["members"], client)
end
hook.Run("OnLeaveTeam", client, index)
end
function PLUGIN:JoinTeam(client, index)
if !index or index and !self.teams[index] then return end
if !self.teams[index]["members"] then return end
table.insert(self.teams[index]["members"], client)
hook.Run("OnJoinTeam", client, index)
end
function PLUGIN:SetTeamOwner(index, client)
if !self.teams[index] then return end
self.teams[index]["owner"] = client
hook.Run("OnSetTeamOwner", client, index)
end
-- Hooks
function PLUGIN:OnCreateTeam(client, index)
self:UpdateTeamMenu()
end
function PLUGIN:OnReassignTeam(index, newIndex)
self:UpdateTeamMenu()
end
function PLUGIN:OnDeleteTeam(index)
self:UpdateTeamMenu()
end
function PLUGIN:OnLeaveTeam(client, index)
self:UpdateTeamMenu()
end
function PLUGIN:OnJoinTeam(client, index)
self:UpdateTeamMenu()
end
function PLUGIN:OnSetTeamOwner(client, index)
self:UpdateTeamMenu()
end
function PLUGIN:PopulateCharacterInfo(client, character, container)
if (LocalPlayer():HasActiveCombineMask() and client:GetNetVar("ProtectionTeam")) then
local curTeam = container:AddRowAfter("name", "curTeam")
curTeam:SetText(L("TeamStatus", client:GetNetVar("ProtectionTeam"), client:GetNetVar("ProtectionTeamOwner") and L("TeamOwnerStatus") or L("TeamMemberStatus")))
curTeam:SetBackgroundColor(client:GetNetVar("ProtectionTeamOwner") and Color(50,150,100) or Color(50,100,150))
end
end
net.Receive("ixPTSync", function()
local bTeams = net.ReadBool()
if (!bTeams) then
PLUGIN.teams = {}
return
end
local teams = net.ReadTable()
PLUGIN.teams = teams or {}
end)
net.Receive("ixPTCreate", function()
local index = net.ReadUInt(8)
local client = net.ReadEntity()
PLUGIN:CreateTeam(client, index)
end)
net.Receive("ixPTDelete", function()
local index = net.ReadUInt(8)
PLUGIN:DeleteTeam(index)
end)
net.Receive("ixPTLeave", function()
local index = net.ReadUInt(8)
local client = net.ReadEntity()
PLUGIN:LeaveTeam(client, index)
end)
net.Receive("ixPTJoin", function()
local index = net.ReadUInt(8)
local client = net.ReadEntity()
PLUGIN:JoinTeam(client, index)
end)
net.Receive("ixPTOwner", function()
local index = net.ReadUInt(8)
local client = net.ReadEntity()
PLUGIN:SetTeamOwner(index, client)
end)
net.Receive("ixPTReassign", function()
local index = net.ReadUInt(8)
local newIndex = net.ReadUInt(8)
PLUGIN:ReassignTeam(index, newIndex)
end)

View File

@@ -0,0 +1,166 @@
--[[
| 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.util.IncludeDir("ixhl2rp/plugins/combineutilities/teams/derma", true)
PLUGIN.teams = {}
function PLUGIN:GetReceivers()
local recievers = {}
for _, client in pairs(player.GetAll()) do
if (client:IsCombine()) then
table.insert(recievers, client)
end
end
return recievers
end
ix.command.Add("PTCreate", {
description = "@cmdPTCreate",
arguments = bit.bor(ix.type.number, ix.type.optional),
OnCheckAccess = function(self, client)
return client:IsCombine()
end,
OnRun = function(self, client, index)
if (!client:IsCombine()) then
return "@CannotUseTeamCommands"
end
if (!index) then
return client:RequestString("@cmdPTCreate", "@cmdCreatePTDesc", function(text) ix.command.Run(client, "PTCreate", {text}) end, "")
end
return PLUGIN:CreateTeam(client, index)
end
})
ix.command.Add("PTJoin", {
description = "@cmdPTJoin",
arguments = ix.type.number,
OnCheckAccess = function(self, client)
return client:IsCombine()
end,
OnRun = function(self, client, index)
if (!client:IsCombine()) then
return "@CannotUsePTCommands"
end
return PLUGIN:JoinTeam(client, index)
end
})
ix.command.Add("PTLeave", {
description = "@cmdPTLeave",
OnCheckAccess = function(self, client)
return client:IsCombine()
end,
OnRun = function(self, client)
if (!client:IsCombine()) then
return "@CannotUsePTCommands"
end
return PLUGIN:LeaveTeam(client)
end
})
ix.command.Add("PTLead", {
description = "@cmdPTLead",
arguments = bit.bor(ix.type.player, ix.type.optional),
OnCheckAccess = function(self, client)
return client:IsCombine()
end,
OnRun = function(self, client, target)
if (!client:IsCombine()) then
return "@CannotUseTeamCommands"
end
if (target == client or !target) then
target = client
end
local index = target:GetNetVar("ProtectionTeam")
if (!PLUGIN.teams[index]) then return "@TargetNoCurrentTeam" end
if (!client:IsDispatch()) then
if (client:GetNetVar("ProtectionTeam") != target:GetNetVar("ProtectionTeam")) then return "@TargetNotSameTeam" end
if (PLUGIN.teams[index]["owner"]) then
if (target == client) then return "@TeamAlreadyHasOwner" end
if (!client:GetNetVar("ProtectionTeamOwner")) then return "@CannotPromoteTeamMembers" end
end
end
if ((target == client or !target) and (PLUGIN:SetTeamOwner(index, target))) then
return "@TeamOwnerAssume"
end
return PLUGIN:SetTeamOwner(index, target)
end
})
ix.command.Add("PTKick", {
description = "@cmdPTKick",
arguments = ix.type.player,
OnCheckAccess = function(self, client)
return client:IsCombine()
end,
OnRun = function(self, client, target)
if (!client:IsCombine()) then
return "@CannotUseTeamCommands"
end
local index = target:GetNetVar("ProtectionTeam")
if (!PLUGIN.teams[index]) then return "@TargetNoCurrentTeam" end
if (client:GetNetVar("ProtectionTeam") != target:GetNetVar("ProtectionTeam") and !client:IsDispatch()) then return "@TargetNotSameTeam" end
if (!client:GetNetVar("ProtectionTeamOwner") and !client:IsDispatch()) then return "@CannotKickTeamMembers" end
PLUGIN:LeaveTeam(target)
return "@KickedFromTeam", target:GetName()
end
})
ix.command.Add("PTReassign", {
description = "@cmdPTReassign",
arguments = {bit.bor(ix.type.number, ix.type.optional), bit.bor(ix.type.number, ix.type.optional)},
OnCheckAccess = function(self, client)
return client:IsCombine()
end,
OnRun = function(self, client, newIndex, oldIndex)
if (!client:IsCombine()) then
return "@CannotUseTeamCommands"
end
local index = client:GetNetVar("ProtectionTeam")
if (!oldIndex and index) then
oldIndex = index
end
if (!client:IsDispatch()) then
if (!PLUGIN.teams[oldIndex]) then return "@NoCurrentTeam" end
if (!client:GetNetVar("ProtectionTeamOwner")) then return "@CannotReassignTeamIndex" end
end
if (newIndex and oldIndex) then
return PLUGIN:ReassignTeam(oldIndex, newIndex)
else
return client:RequestString("@cmdPTReassign", "@cmdReassignPTDesc", function(text) ix.command.Run(client, "PTReassign", {text, oldIndex}) end, "")
end
end
})

View File

@@ -0,0 +1,230 @@
--[[
| 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
util.AddNetworkString("ixPTSync")
util.AddNetworkString("ixPTCreate")
util.AddNetworkString("ixPTDelete")
util.AddNetworkString("ixPTJoin")
util.AddNetworkString("ixPTLeave")
util.AddNetworkString("ixPTOwner")
util.AddNetworkString("ixPTReassign")
function PLUGIN:CreateTeam(client, index, bNetworked, bNoNotif)
if (IsValid(client) and client:GetNetVar("ProtectionTeam")) then
return "@AlreadyHasTeam"
end
if (self.teams[index]) then
return "@TeamAlreadyExists", tostring(index)
end
if (index > 99 or index < 1) then
return "@TeamMustClamp"
end
self.teams[index] = {
owner = client,
members = {client}
}
if (IsValid(client)) then
client:SetNetVar("ProtectionTeam", index)
client:SetNetVar("ProtectionTeamOwner", true)
end
if (!bNetworked) then
net.Start("ixPTCreate")
net.WriteUInt(index, 8)
net.WriteEntity(client)
net.Send(self:GetReceivers())
end
hook.Run("OnCreateTeam", client, index)
if (!bNoNotif) then
ix.combineNotify:AddNotification("NTC:// " .. client:GetCombineTag() .. " has established Protection-Team " .. index, Color(0, 145, 255, 255))
end
return "@TeamCreated", tostring(index)
end
function PLUGIN:ReassignTeam(index, newIndex, bNetworked)
if (newIndex > 99 or newIndex < 1) then
return "@TeamMustClamp"
end
if (self.teams[newIndex]) then
return "@TeamAlreadyExists", tostring(index)
end
local curTeam = self.teams[index]
self:DeleteTeam(index, true, true)
self:CreateTeam(curTeam["owner"], newIndex, true, true)
self.teams[newIndex]["members"] = curTeam["members"]
for _, client in pairs(curTeam["members"]) do
client:SetNetVar("ProtectionTeam", newIndex)
end
if (!bNetworked) then
net.Start("ixPTReassign")
net.WriteUInt(index, 8)
net.WriteUInt(newIndex, 8)
net.Send(self:GetReceivers())
end
hook.Run("OnReassignTeam", index, newIndex)
ix.combineNotify:AddNotification("NTC:// Protection-Team " .. index .. " re-assigned as Protection-Team " .. newIndex, Color(0, 145, 255, 255))
return "@TeamReassigned", tostring(index), tostring(newIndex)
end
function PLUGIN:SetTeamOwner(index, client, bNetworked)
local curOwner = self.teams[index]["owner"]
if (IsValid(curOwner)) then
curOwner:SetNetVar("ProtectionTeamOwner", nil)
end
self.teams[index]["owner"] = client
if (IsValid(client)) then
client:SetNetVar("ProtectionTeamOwner", true)
end
if (!bNetworked) then
net.Start("ixPTOwner")
net.WriteUInt(index, 8)
net.WriteEntity(client)
net.Send(self:GetReceivers())
end
hook.Run("OnSetTeamOwner", client, index)
if (IsValid(client)) then
ix.combineNotify:AddNotification("NTC:// " .. client:GetCombineTag() .. " designated as Protection-Team " .. index .. " Leader", Color(0, 145, 255, 255))
return "@TeamOwnerSet", client:GetName()
end
end
function PLUGIN:DeleteTeam(index, bNetworked, bNoNotif)
self.teams[index] = nil
for _, client in pairs(self:GetReceivers()) do
if (client:GetNetVar("ProtectionTeam") == index) then
client:SetNetVar("ProtectionTeam", nil)
if (client:GetNetVar("ProtectionTeamOwner")) then
client:SetNetVar("ProtectionTeamOwner", nil)
end
end
end
if (!bNetworked) then
net.Start("ixPTDelete")
net.WriteUInt(index, 8)
net.Send(self:GetReceivers())
end
if (!bNoNotif) then
ix.combineNotify:AddNotification("NTC:// Protection-Team " .. index .. " has been disbanded", Color(0, 145, 255, 255))
end
hook.Run("OnDeleteTeam", index)
end
function PLUGIN:JoinTeam(client, index, bNetworked)
if (client:GetNetVar("ProtectionTeam")) then
return "@TeamMustLeave"
end
if (index > 99 or index < 1) then
return "@TeamMustClamp"
end
if (!self.teams[index]) then
return "@TeamNonExistent", tostring(index)
end
table.insert(self.teams[index]["members"], client)
client:SetNetVar("ProtectionTeam", index)
if (!bNetworked) then
net.Start("ixPTJoin")
net.WriteUInt(index, 8)
net.WriteEntity(client)
net.Send(self:GetReceivers())
end
hook.Run("OnJoinTeam", client, index)
ix.combineNotify:AddNotification("NTC:// " .. client:GetCombineTag() .. " has interlocked into Protection-Team " .. index, Color(0, 145, 255, 255))
return "@JoinedTeam", index
end
function PLUGIN:LeaveTeam(client, bNetworked)
if (!client:GetNetVar("ProtectionTeam")) then
return "@NoCurrentTeam"
end
local index = client:GetNetVar("ProtectionTeam")
local curTeam = self.teams[index]
if (curTeam) then
table.RemoveByValue(self.teams[index]["members"], client)
client:SetNetVar("ProtectionTeam", nil)
if (!bNetworked) then
net.Start("ixPTLeave")
net.WriteUInt(index, 8)
net.WriteEntity(client)
net.Send(self:GetReceivers())
end
if (client:GetNetVar("ProtectionTeamOwner")) then
self:SetTeamOwner(index, nil)
end
hook.Run("OnLeaveTeam", client, index)
ix.combineNotify:AddNotification("NTC:// " .. client:GetCombineTag() .. " has detached from Protection-Team " .. index, Color(0, 145, 255, 255))
return "@LeftTeam", index
end
end
function PLUGIN:Tick()
local curTime = CurTime()
if (!self.tick or self.tick < curTime) then
self.tick = curTime + 30
for index, teamTbl in pairs(self.teams) do
if (table.IsEmpty(teamTbl["members"])) then
self:DeleteTeam(index)
end
end
end
end
function PLUGIN:PlayerDisconnected(client)
if (client:GetNetVar("ProtectionTeam")) then
self:LeaveTeam(client)
end
end

View File

@@ -0,0 +1,102 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
include('shared.lua')
local glowMaterial = ix.util.GetMaterial("sprites/glow04_noz")
local color_red = Color(255, 0, 0, 255)
function ENT:Initialize()
self.buttons = {}
end
function ENT:Draw()
self:DrawModel()
local width, height = 260, 135
local ang = self:GetAngles()
local pos = self:GetPos() + ang:Up() * 60 - ang:Right() * 4.1 - ang:Forward() * 13
ang:RotateAroundAxis(ang:Right(), 90)
ang:RotateAroundAxis(ang:Up(), -65)
ang:RotateAroundAxis(ang:Right(), -90)
local display = self.Displays[self:GetDisplay()] or self.Displays[6]
cam.Start3D2D(pos, ang, 0.1)
render.PushFilterMin(TEXFILTER.NONE)
render.PushFilterMag(TEXFILTER.NONE)
surface.SetDrawColor(Color(255, 255, 255, 250))
surface.SetMaterial(ix.util.GetMaterial("willardnetworks/datafile/workshifterminal.png"))
surface.DrawTexturedRect(0, 0, width, height)
surface.SetDrawColor(Color(16, 16, 16, 100))
surface.DrawRect(10, 5, width - 20, height - 10)
surface.SetDrawColor(Color(72, 255, 243, 10))
surface.DrawOutlinedRect(10, 5, width - 20, height - 10)
surface.SetDrawColor(Color(255, 255, 255, 16))
surface.DrawRect(10, (height - 5) / 1.9 + math.sin(CurTime() * 4) * (height + 8) / 2.3, width - 20, 1)
local alpha = 191 + 64 * math.sin(CurTime() * 4)
local color = ColorAlpha(display[2], alpha)
draw.SimpleText("Terminal Cykli", "MenuFont", width / 2, height * 0.35, Color(255, 255, 255, alpha), TEXT_ALIGN_CENTER)
draw.SimpleText(display[1], "MenuFont", width / 2, height * 0.6, color, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
if (self.buttons) then
for k, _ in pairs(self.buttons) do
local closest = self:GetNearestButton()
local thisText = "Enter CID"
if (closest == k) then
cam.Start3D2D(self.buttons[k], ang, 0.1)
draw.SimpleText(thisText, "MenuFont", 0, -30, Color(255, 255, 255, 255), TEXT_ALIGN_CENTER)
cam.End3D2D()
end
end
end
render.PopFilterMin()
render.PopFilterMag()
cam.End3D2D()
render.SetMaterial(glowMaterial)
if (self.buttons) then
local position = self:GetPos()
local f, r, u = self:GetForward(), self:GetRight(), self:GetUp()
self.buttons[1] = position + f*-5.6 + r*5.6 + u*46
local closest = self:GetNearestButton()
for k, v in pairs(self.buttons) do
local thisColor = Color(255, 255, 255, 255)
if (closest != k) then
thisColor.a = thisColor == color_red and 100 or 75
else
thisColor.a = 230 + (math.sin(RealTime() * 7.5) * 25)
end
if (LocalPlayer():KeyDown(IN_USE) and closest == k) then
thisColor = table.Copy(thisColor)
thisColor.r = math.min(thisColor.r + 100, 255)
thisColor.g = math.min(thisColor.g + 100, 255)
thisColor.b = math.min(thisColor.b + 100, 255)
end
render.DrawSprite(v, 4, 4, thisColor)
end
end
end

View File

@@ -0,0 +1,122 @@
--[[
| 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( "cl_init.lua" ) -- Make sure clientside
AddCSLuaFile( "shared.lua" ) -- and shared scripts are sent.
include('shared.lua')
local PLUGIN = PLUGIN
function ENT:OnInitialize()
self:SetDisplay(9)
end
function ENT:SaveTerminalLocations()
ix.saveEnts:SaveEntity(self)
end
function ENT:SetGroups(bUse)
end
function ENT:CheckStartedWorkshift()
if !PLUGIN:CheckStartedWorkshift(self) then
self:SetDisplay(9)
self:EmitSound("buttons/button8.wav")
self:ResetInfo()
return false
end
return true
end
function ENT:StopWorkshift(client)
if !self.workshiftStarted then
self:ResetInfo()
self:EmitSound("buttons/button8.wav")
return
end
PLUGIN:StopWorkshift(self, client)
end
function ENT:StartWorkshift(client)
if self.workshiftStarted then
self:ResetInfo()
self:EmitSound("buttons/button8.wav")
return
end
self:SetDisplay(3)
timer.Simple(1, function()
if IsValid(self) then
self:SetDisplay(1)
end
end)
self.workshiftStarted = true
self:ResetInfo()
end
function ENT:ResetInfo()
self.canUse = true
self.activePlayer = nil
self.activeCharacter = nil
end
function ENT:OnUse(client)
local button = self:GetNearestButton(client)
if (button) then
self:EmitSound("buttons/lightswitch2.wav")
if !self:CheckStartedWorkshift() then
self:EmitSound("buttons/button8.wav")
self:ResetInfo()
return false
end
self:CheckForCID(client)
else
client:NotifyLocalized("Musisz użyć jednego z przycisków!")
self:ResetInfo()
end
end
function ENT:ReadyForAnother()
timer.Simple(1, function()
if IsValid(self) then
self:SetDisplay(1)
self:ResetInfo()
end
end)
end
function ENT:OnSuccess(idCard, genericData, client)
self:SetDisplay(6)
self:EmitSound("buttons/button14.wav")
self:ReadyForAnother()
if (client:IsVortigaunt()) then
ix.combineNotify:AddNotification("LOG:// Podmiot " .. string.upper("o identyfikatorze biotycznego zasobu: #") .. genericData.cid .. " dołączył do Cyklu pracy")
else
ix.combineNotify:AddNotification("LOG:// Podmiot '" .. genericData.name .. "' dołączył do Cyklu pracy", nil, client)
end
PLUGIN:AddToWorkshift(client, idCard, genericData, self)
end
function ENT:AlreadyParticipated()
self:SetDisplay(10)
self:EmitSound("buttons/button8.wav")
self:ReadyForAnother()
end

View File

@@ -0,0 +1,77 @@
--[[
| 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/
--]]
ENT.Type = "anim"
ENT.PrintName = "Workshift Terminal"
ENT.Base = "ix_terminal"
ENT.Author = "Fruity"
ENT.Contact = "Willard Networks"
ENT.Purpose = "Start and stop workshifts via an entity."
ENT.Instructions = "Press E to enter CID, use the buttons to start/stop."
ENT.Category = "HL2 RP"
ENT.Spawnable = true
ENT.AdminOnly = true
ENT.PhysgunDisable = true
ENT.bNoPersist = true
ENT.model = "models/willard/combine/checkin.mdl"
ENT.workshiftStarted = false
ENT.participants = {}
ENT.canMalfunction = true
ENT.Displays = {
[1] = {"OCZEKIWANIE NA ID", Color( 255, 255, 180 ), true},
[2] = {"SPRAWDZANIE", Color(255, 200, 0)},
[3] = {"ROZPOCZĘTO CYKL", Color(0, 255, 0)},
[4] = {"PRZEŁADOWYWANIE", Color(255, 200, 0)},
[5] = {"OFFLINE", Color(255, 0, 0), true},
[6] = {"SUKCES", Color( 0, 255, 180 )},
[7] = {"ZAKOŃCZONO CYKL", Color(255, 0, 0)},
[8] = {"BRAK INFORMACJI", Color(0, 255, 0)},
[9] = {"CYKL NIEAKTYWNY", Color(255, 0, 0)},
[10] = {"JUŻ UCZESTNICZY", Color(255, 0, 0)},
[11] = {"WSTRZYMANO REJESTRACJĘ", Color(255, 0, 0)}
}
ENT.buttons = {}
function ENT:SetupDataTables()
self:NetworkVar("Int", 0, "Display")
end
function ENT:GetNearestButton(client)
client = client or (CLIENT and LocalPlayer())
if (self.buttons) then
if (SERVER) then
local position = self:GetPos()
local f, r, u = self:GetForward(), self:GetRight(), self:GetUp()
self.buttons[1] = position + f*-5.6 + r*5.6 + u*46
end
local data = {}
data.start = client:GetShootPos()
data.endpos = data.start + client:GetAimVector()*96
data.filter = client
local trace = util.TraceLine(data)
local hitPos = trace.HitPos
if (hitPos) then
for k, v in pairs(self.buttons) do
if (v:Distance(hitPos) <= 2) then
return k
end
end
end
end
end

View File

@@ -0,0 +1,145 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLUGIN = PLUGIN
function PLUGIN:StartWorkshift()
SetNetVar("WorkshiftStarted", true)
end
function PLUGIN:StopWorkshift(ent)
ent.workshiftPaused = ent.workshiftPaused or false
ent.savedInfo = ent.savedInfo or {}
ent.workshiftStarted = false
ent.workshiftPaused = false
ent.participants = {}
ent.savedInfo = {}
ent:ResetInfo()
ent:SetDisplay(9)
ent:EmitSound("ambient/machines/combine_terminal_idle2.wav")
end
function PLUGIN:EndWorkshift(tSaved, client)
local character = client:GetCharacter()
local datafields = {"genericdata", "datafilelogs"}
if tSaved and istable(tSaved) and !table.IsEmpty(tSaved) then
for genericID, tInfo in pairs(tSaved) do
local coupon = tInfo.coupon or false
local points = tInfo.points or 0
local dataSelect = mysql:Select("ix_characters_data")
dataSelect:Where("id", genericID)
dataSelect:WhereIn("key", datafields)
dataSelect:Callback(function(dataSelectResult)
if (!istable(dataSelectResult) or #dataSelectResult == 0) then
return
end
local file = {}
for _, v in ipairs(dataSelectResult) do
file[v.key] = util.JSONToTable(v.data or "")
end
local limitCount = 0
for _, v in pairs(file["datafilelogs"]) do
if !v.points then
continue
end
if isnumber(v.date) and os.date("%d/%m/%Y", v.date) == os.date("%d/%m/%Y") then
limitCount = limitCount + v.points
end
end
if ((points + limitCount) > 20 or (points + limitCount) < -20) then
PLUGIN:AddLog(client, file["datafilelogs"], file["genericdata"], client:Name(), 0, "Finished Workshift", true, true)
else
if (file["genericdata"].cohesionPoints) then
file["genericdata"].cohesionPoints = !file["genericdata"].combine and math.Clamp(file["genericdata"].cohesionPoints + points, 0, 200) or file["genericdata"].cohesionPoints + points
file["genericdata"].cohesionPointsDate = os.time()
else
file["genericdata"].socialCredits = !file["genericdata"].combine and math.Clamp(file["genericdata"].socialCredits + points, 0, 200) or file["genericdata"].socialCredits + points
file["genericdata"].socialCreditsDate = os.time()
end
PLUGIN:AddLog(client, file["datafilelogs"], file["genericdata"], client:Name(), points, "Finished Workshift", true, true)
PLUGIN:EditDatafile(client, file["genericdata"], true, true)
end
local couponCharacter = ix.char.loaded[genericID]
if couponCharacter and coupon != false then
if coupon == "PODSTAWOWY" then
couponCharacter:SetPurchasedItems("coupon_basic", 1)
elseif coupon == "ŚREDNI" then
couponCharacter:SetPurchasedItems("coupon_medium", 1)
else
couponCharacter:SetPurchasedItems("coupon_priority", 1)
end
end
end)
dataSelect:Execute()
end
end
SetNetVar("WorkshiftStarted", false)
end
function PLUGIN:PauseWorkshift(ent, client, bPaused)
ent.workshiftPaused = bPaused
end
function PLUGIN:SaveWorkshift(tSaved, ent)
ent.savedInfo = tSaved
end
function PLUGIN:CheckStartedWorkshift(ent)
if ent.workshiftStarted then return true end
return false
end
function PLUGIN:AddToWorkshift(client, idCard, genericData, ent)
if ent.workshiftPaused then
ent:SetDisplay(11)
ent:ReadyForAnother()
return false
end
if ent.participants[genericData.id] then
ent:AlreadyParticipated()
ent:ResetInfo()
return false
end
ent.participants[genericData.id] = {genericData.cid, genericData.name}
local pointsToday = 0
local queryObj = mysql:Select("ix_characters_data")
queryObj:Where("id", genericData.id)
queryObj:Where("key", "datafilelogs")
queryObj:Select("data")
queryObj:Callback(function(result)
if (!istable(result) or !result[1]) then return end
if !result[1].data then return end
for _, tLog in pairs(util.JSONToTable(result[1].data)) do
if tLog.points and tLog.points != 0 and tLog.date and isnumber(tLog.date) and os.date("%d/%m/%Y", tLog.date) == os.date("%d/%m/%Y") then
pointsToday = pointsToday + tLog.points
end
end
ent.participants[genericData.id][3] = pointsToday
end)
queryObj:Execute()
end