This commit is contained in:
lifestorm
2024-08-04 22:55:00 +03:00
parent 8064ba84d8
commit 73479cff9e
7338 changed files with 1718883 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("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, "caméras", 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, "lié la maj", 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("Choisir")
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, "mises à jours", true)
updates.DoClick = function()
if !ix.data.Get("CameraConsoleLinkedUpdate") then
LocalPlayer():NotifyLocalized("Aucune mise à jour liée.")
return
end
local updatePanel = vgui.Create("DFrame")
updatePanel:SetSize(SScaleMin(600 / 3), SScaleMin(700 / 3))
updatePanel:Center()
updatePanel:MakePopup()
Schema:AllowMessage(updatePanel)
updatePanel:SetTitle("Mises à jour")
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);'>Aucune mises à jour.</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("Retour")
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( "Suivant" )
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( "Précédent" )
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( "Bloquer" )
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("Caméra "..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( "Caméra ".. 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("darkrp/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("Vous devez attendre avant de pouvoir l'utiliser !")
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 = "Ordinateur"
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( "Command Console", "MenuFont", width / 2, 15, Color( 255, 255, 255, alpha ), TEXT_ALIGN_CENTER )
draw.SimpleText( "Waiting for user", "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:// Console ouverte par " .. 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:// Visuel sur l'Anti-Citoyen " .. 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:// Visuel sur le citoyen fiché " .. name .. ", #" .. cid, Color(255, 255, 0, 255), activator, activator:GetPos())
end
end
if (activator:Team() == FACTION_VORT and character:GetBackground() != "Biotique" and character:GetBackground() != "Collaborateur") 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:// Visuel sur le biotique #" .. 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("Vous devez attendre avant de pouvoir l'utiliser !")
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("Vous n'avez pas d'accès ou vous ne portez pas de combinaison.")
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 = "Ordinateur de Médecin"
ENT.Category = "HL2 RP"
ENT.Spawnable = true
ENT.AdminOnly = true
ENT.PhysgunDisable = true
ENT.bNoPersist = true
ENT.Displays = {
[1] = {"EN ATTENTE", Color( 255, 255, 180 ), true},
[2] = {"RÉCUPÉRATION INFO.", Color(0, 255, 0)},
[3] = {"RECHARGEMENT", Color(255, 200, 0)},
[4] = {"HORS-LIGNE", 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 Citoyen", "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("Vous devez attendre avant de pouvoir l'utiliser !")
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() == "Collaborateur") then
ix.combineNotify:AddNotification("LOG:// Le sujet " .. string.upper("Carte d'identification des biotiques actifs:") .. " #" .. genericData.cid .. " a utilisé un Terminal", nil, client)
else
ix.combineNotify:AddNotification("LOG:// Le sujet " .. string.upper("Collier des biotiques actifs:") .. " #" .. character:GetCollarID() .. " a utilisé un Terminal", nil, client)
end
else
ix.combineNotify:AddNotification("LOG:// Le sujet '" .. genericData.name .. "' a utilisé un Terminal", 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:// Tentative d'utilisation de la carte CID inactive #" .. idCard:GetData("cid", 00000) .. " détéctée.")
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 "Recherché" or "Anti-Citoyen"
self:CreateCombineAlert(client, "WRN:// " .. text .. " Activité de carte CID détectée")
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:// Tentative d'utilisation de la carte CID inactive #" .. idCard:GetData("cid", 00000) .. " détéctée.", FREQ_LIMIT)
return false
end
local isBOL = genericData.bol
local isAC = genericData.anticitizen
if (isBOL or isAC) then
local text = isBOL and "Recherché" or "Anti-Citoyen"
entity:CreateCombineAlert(client, "WRN:// " .. text .. " Activité de carte CID détéctée", 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:// Le sujet '" .. name .. "' a envoyé un message par le terminal", 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("Quelqu'un vient d'envoyer un message via le terminal !")
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:// Tentative de 51B ; atteinte à la propriété", nil, client, client:GetPos())
end)

View File

@@ -0,0 +1,41 @@
--[[
| 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 Citoyen"
ENT.Author = "Fruity"
ENT.Contact = "Willard Networks"
ENT.Purpose = "View datafile info and more via entity."
ENT.Instructions = "Appuyez sur 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.Displays = {
[1] = {"EN ATTENTE DE CID", Color( 255, 255, 180 ), true},
[2] = {"VÉRIFICATION", Color(255, 200, 0)},
[3] = {"RÉCUPÉRATION INFO.", Color(0, 255, 0)},
[4] = {"RECHARGEMENT", Color(255, 200, 0)},
[5] = {"HORS-LIGNE", Color(255, 0, 0), true},
[6] = {"EN ATTENTE DE CID", Color( 255, 255, 180 )},
[7] = {"PREPARATION", Color(0, 255, 0)},
[8] = {"AUCUNE INFO.", 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"
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("Vous n'avez pas accès au 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,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 = "Ordinateur de Citoyen"
ITEM.uniqueID = "cit_computer"
ITEM.model = "models/willardnetworks/props/willard_computer.mdl"
ITEM.width = 2
ITEM.height = 2
ITEM.description = "Un ordinateur qui peut enregistrer des notes et verrouiller des utilisateurs."
ITEM.category = "Ordinateurs"
ITEM.functions.Place = {
name = "Placer",
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("Vous ne pouvez pas placer ceci maintenant !")
return false
else
client:NotifyLocalized("Vous ne pouvez pas le placer si loin !")
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 = "Disquette"
ITEM.model = "models/props/cs_office/computer_caseb_p9a.mdl"
ITEM.skin = 1
ITEM.width = 1
ITEM.height = 1
ITEM.description = "Stockage sur disque composé d'un disque mince et flexible magnétique, utilisé pour le chargement d'informations."
ITEM.category = "Ordinateurs"
function ITEM:GetName()
if self:GetData("customName", false) then
return self:GetData("customName", false)
end
return self.name
end
ITEM.functions.Place = {
name = "Insérer dans l'ordinateur",
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 = "Nommer disquette",
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,63 @@
--[[
| 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 = "Ordinateur de Médecin"
ITEM.uniqueID = "med_computer"
ITEM.model = "models/willardnetworks/props/willard_computer.mdl"
ITEM.skin = 1
ITEM.width = 2
ITEM.height = 2
ITEM.description = "Un ordinateur qui permet de consulter les dossiers médicaux."
ITEM.category = "Ordinateurs"
ITEM.functions.Place = {
name = "Placer",
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("Vous ne pouvez pas placer ceci maintenant !")
return false
else
client:NotifyLocalized("Vous ne pouvez pas le placer si loin !")
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 de l'UTC"
ITEM.description = "PDA de l'UTC."
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 = "DATA-PAD"
ITEM.description = "Un data-pad fabriqué par le Cartel pour les unités de la protection civile & les membres de l'UTC."
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 = "MEMBER",
TeamOwnerStatus = "LEADER",
tabProtectionTeam = "Protection Team",
tabCreateTeam = "CREATE PT",
tabJoinTeam = "JOIN PT",
tabLeaveTeam = "LEAVE PT",
TeamTransferOwner = "Transfer Lead",
TeamKickMember = "Kick Member",
TeamReassign = "Reassign Index",
CannotUseTeamCommands = "You cannot use PT commands!",
CannotPromoteTeamMembers = "You cannot promote PT members!",
CannotKickTeamMembers = "You cannot kick PT members!",
CannotReassignTeamIndex = "You cannot reassign PT index!",
NoCurrentTeam = "You are not apart of a PT!",
TargetNoCurrentTeam = "The person you are trying to promote is not apart of a PT!",
TargetNotSameTeam = "The person you are trying to promote is not apart of the same PT!",
TeamMustClamp = "You must provide a number between 1-99!",
TeamMustLeave = "You must leave your current PT before joining a new one!",
TeamAlreadyHasOwner = "There is already a PT lead!",
TeamAlreadyExists = "A PT with index '%s' already exists!",
TeamNonExistent = "PT '%s' doesn't exist!",
AlreadyHasTeam = "You are already apart of a PT!",
KickedFromTeam = "You've kicked %s from the PT.",
TeamCreated = "PT '%s' successfully created.",
TeamReassigned = "PT '%s' successfully reassigned to '%s'.",
TeamOwnerSet = "The new PT lead has been set to %s.",
TeamOwnerAssume = "You've assumed PT lead.",
JoinedTeam = "Successfully joined PT '%s'.",
LeftTeam = "Successfully left PT '%s'.",
cmdCreatePTDesc = "Enter the number index for your new Protection Team. (1-99)",
cmdReassignPTDesc = "Enter a new number index for your current Squad. (1-99)",
cmdPTCreate = "Create a Protection Team.",
cmdPTLeave = "Leave your Protection Team.",
cmdPTLead = "Promote a PT member to PT lead or assume the lead position.",
cmdPTKick = "Kick a PT member.",
cmdPTReassign = "Reassign PT number index.",
cmdPTJoin = "Join a 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 = "E-%s",
TeamStatus = "E-%s %s",
TeamMemberStatus = "MEMBRE",
TeamOwnerStatus = "LEADER",
tabProtectionTeam = "Escouade",
tabCreateTeam = "CRÉER ESCOUADE",
tabJoinTeam = "REJOINDRE ESCOUADE",
tabLeaveTeam = "QUITTER ESCOUADE",
TeamTransferOwner = "Transferer LEAD",
TeamKickMember = "Expulser un membre",
TeamReassign = "Réaffecter l'index ",
CannotUseTeamCommands = "Vous ne pouvez pas utiliser les commandes de l'escouade !",
CannotPromoteTeamMembers = "Vous ne pouvez pas promouvoir les membres de l'escouade !",
CannotKickTeamMembers = "Vous ne pouvez pas expulser les membres de l'escouade !",
CannotReassignTeamIndex = "Vous ne pouvez pas réaffecter l'index de l'escouade !",
NoCurrentTeam = "Vous ne faites pas partie d'une escouade !",
TargetNoCurrentTeam = "La personne que vous essayez de promouvoir ne fait pas partie d'une escouade !",
TargetNotSameTeam = "La personne que vous essayez de promouvoir ne fait pas parti de la même escouade !",
TeamMustClamp = "Vous devez fournir un nombre entre 1-99!",
TeamMustLeave = "Vous devez quitter votre escouade actuelle avant d'en rejoindre une autre !",
TeamAlreadyHasOwner = "Il y a déjà un leader d'escouade",
TeamAlreadyExists = "Une escouade avec l'index '%s' existe déjà !",
TeamNonExistent = "L'escouade '%s' n'existe pas !",
AlreadyHasTeam = "Vous êtes déjà en dehors d'une escouade !",
KickedFromTeam = "Vous avez expulsé %s de l'escouade.",
TeamCreated = "Escouade '%s' crée avec succès.",
TeamReassigned = "L'escouade '%s' a été réaffectée avec succès à '%s'.",
TeamOwnerSet = "La lead de l'escouade a été donné à %s.",
TeamOwnerAssume = "Vous êtes devenu leader.",
JoinedTeam = "Vous avez rejoins l'escouade '%s'.",
LeftTeam = "Vous avez quitté l'escouade '%s'.",
cmdCreatePTDesc = "Saisissez l'index des numéros de votre nouvelle escouade. (1-99)",
cmdReassignPTDesc = "Entrez un nouvel index numérique pour votre escouade actuelle. (1-99)",
cmdPTCreate = "Créer une escouade.",
cmdPTLeave = "Quitter votre escouade.",
cmdPTLead = "Promouvoir un membre Leader ou assumer la position de Leader.",
cmdPTKick = "Expulser un membre de l'escouade.",
cmdPTReassign = "Réaffecter l'index des numéros de l'escouade.",
cmdPTJoin = "Rejoignez une escouade."
}

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 = false,
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 = "Database"
})
ix.command.Add("SetDatafilePoints", {
description = "Définissez des points de loyauté pour les fichiers de données.",
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 = "Ouvrez le fichier de données en tant que Overwatch ou 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("Vous n'avez pas accès au datapad")
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("darkrp/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 = "INACTIVE"
genericdata.cid = "N/A"
genericdata.name = nil
if (character:HasFlags("N") or character:GetBackground() == "Collaborator") then
genericdata.nulled = "ACTIVE"
end
for _, v in pairs(character:GetInventory():GetItems()) do
if (table.HasValue({"Vortigaunt Collar", "Vortigaunt Collar (fake)"}, 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("New format successfully applied to your datafile.")
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 .. " performing identity inspection on " .. string.upper("biotic asset:") .. " #" .. 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 .. " performing identity inspection on " .. string.upper("biotic asset identification card:") .. " #" .. file["genericdata"].cid)
end
else
ix.combineNotify:AddNotification("LOG:// " .. author .. " performing identity inspection on '" .. 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("You do not have access to this datafile!")
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("You do not have access to this datafile!")
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 .. " performing identity inspection on '" .. 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("You do not have access to this datafile!")
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("You do not have access to this datafile!")
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 .. " performing identity inspection on '" .. 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("You cannot send an empty crime report.") 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:// Crime report submitted by " .. 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:// Crime Report ID #" .. key .. " marked as " .. (bUnResolve and "unresolved" or "resolved") .. " by " .. 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:// Crime Report ID #" .. key .. (bUnArchive and " unarchived" or " archived") .. " by " .. 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("The owner of the character needs to be online for the reset to work.")
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:// Retrieving updated Overwatch Datafile update Manifest")
timer.Simple(1, function()
ix.combineNotify:AddNotification("NTC:// New Datafile Update published by " .. 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:// Retrieving updated Overwatch Datafile update Manifest")
timer.Simple(1, function()
ix.combineNotify:AddNotification("NTC:// Datafile Update ID #" .. id .. " deleted by " .. 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:// Retrieving updated Overwatch Datafile update Manifest")
timer.Simple(1, function()
ix.combineNotify:AddNotification("NTC:// Datafile Update ID #" .. id .. " updated by " .. 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("It's not a shop!") 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 >= 90 then
loyalists[v.id] = data
end
if isstring(loyaltyStatus) and loyaltyStatus != "aucun" 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:// Subject '" .. string.upper(genericdata.name or genericdata.collarID) .. "' " .. (loggedAction == "permit" and "Datafile Permit" or loggedAction and "Additional Wages" or "Loyalty Status") .. " revoked by " .. 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("You cannot remove this log because you are not high enough rank or you are not wearing your combine suit!")
return false
end
local author = client:IsDispatch() and "Overwatch" or client:GetCombineTag()
ix.combineNotify:AddNotification("NTC:// Subject '" .. string.upper(subject) .. "' Datafile log removed by " .. 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:// Subject '" .. string.upper(subject) .. "' Datafile 'MEDICAL' entry removed by " .. 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:// Subject '" .. string.upper(subject) .. "' Datafile 'VIOLATION' entry removed by " .. 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 = 60
local designatedStatus = "N/A"
local anticitizen = false
if (string.utf8lower(character:GetBackground()) == "citoyen loyal") then
standardCredits = 60
elseif (string.utf8lower(character:GetBackground()) == "nomade") 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 = "INACTIF",
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 = "AUCUN",
wages = 0,
bypassCommunion = false,
housing = false,
shop = false,
}
if character:GetBackground() == "Collaborateur" 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.." YEUX",
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 = "AUCUN",
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 = "ARRIVÉE DANS LA CITÉ",
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:// Sujet '" .. string.upper(genericdata.name or genericdata.collarID) .. "' " .. action .. " par " .. 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:// Subject '" .. string.upper(genericdata.name or genericdata.collarID) .. "' Datafile 'GENERIC' entry registered by " .. 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:// Subject '" .. string.upper(genericdata.name or genericdata.collarID) .. "' Datafile 'VIOLATION' entry registered by " .. 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:// Subject '" .. string.upper(genericdata.name or genericdata.collarID) .. "' Additional Wages set to " .. wages .. " by " .. 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:// Subject '" .. string.upper(genericdata.name or genericdata.collarID) .. "' Loyalty Status updated to '" .. status .. "' by " .. 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:// Subject '" .. string.upper(genericdata.name or genericdata.collarID) .. "' Communion Bypass " .. (bBypass and "enabled" or "disabled") .. " by " .. 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:// Subject '" .. string.upper(genericdata.name or genericdata.collarID) .. "' Datafile 'MEDICAL' entry registered by " .. 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:// Subject '" .. string.upper(genericdata.name or genericdata.collarID) .. "' Datafile Permits updated by " .. 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("Saved your personal notes.")
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("darkrp/plugins/combineutilities/pda", true)
ix.util.IncludeDir("darkrp/plugins/combineutilities/teams", true)
ix.util.IncludeDir("darkrp/plugins/combineutilities/consoles", true)
ix.util.IncludeDir("darkrp/plugins/combineutilities/workshifts", true)
ix.plugin.LoadEntities("darkrp/plugins/combineutilities/workshifts/entities")
ix.util.Include("sv_groupmessaging.lua")
ix.util.Include("sv_plugin.lua")
ix.flag.Add("L", "Effacer les logs du DATAPAD.")
ix.lang.AddTable("english", {
cmdCharTogglePermit = "Gives or removes a character's permit, (dis)allowing them to use the bartering menu.",
togglePermit = "You have %s %s's bartering permit.",
togglePermitTarget = "%s has %s your bartering permit.",
cmdMassReward = "Give SC to multiple CP units at once. Use 'all' to give to all CP's.\nEnter a space-separated list of (partial) names to give to specific units.",
cmdAmputate = "Boosts your damage against the person you are looking at.\nBoost is only valid for 60 seconds. Target must be tied or KO.\nIf the target dies, the admins are alerted to PK the target.",
identityInspection = "%s %s performing identity inspection on %s, #%s",
})
ix.lang.AddTable("french", {
cmdCharTogglePermit = "Donne ou retire le permis d'un personnage, lui (dés)autorisant à utiliser le menu de commerce.",
togglePermit = "Vous avez le permis de commerce de %s %s.",
togglePermitTarget = "%s a %s votre permis de commerce.",
cmdMassReward = "Donnez CS à plusieurs unités PC à la fois. Utilisez 'tous' pour donner à tous les PC.\nEntrez une liste séparée par des espaces de noms (partiels) à donner à des unités spécifiques.",
cmdAmputate = "Augmente vos dégâts contre la personne que vous regardez.\nLe boost n'est valable que pendant 60 secondes. La cible doit être attaché ou KO.\nSi la cible meurt, les admins sont alertés pour PK la cible.",
identityInspection = "%s %s effectue une inspection d'identité sur %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.char.RegisterVar("hasDatafile", {
default = false,
field = "hasDatafile",
fieldType = ix.type.bool,
bNoDisplay = true,
bNoNetworking = true,
})
ix.config.Add("communionSCRequirement", 150, "Quantité de CS nécessaire pour utiliser le terminal communion.", nil, {
data = {min = 101, max = 720},
catégorie = "Terminal Citoyen"
})
ix.config.Add("maxWorkshiftSocialCredits", 15, "Le montant maximum de crédits sociaux donnés à l'atelier.", nil, {
data = {min = 1, max = 20},
category = "Poste de Travail"
})
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("Entrez un montant valide de CS !")
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("Vous avez reçu "..sc.." crédits stérilisés.")
else
v:Notify("Vous avez perdu "..math.abs(sc).." crédits stérilisés.")
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("Vous avez reçu "..sc.." crédits stérilisés.")
else
v:Notify("Vous avez perdu "..math.abs(sc).." crédits stérilisés.")
end
break
end
end
end
end
if (sc > 0) then
client:ChatNotify("Vous avez donné "..sc.." scrédits stérilisés à : "..table.concat(given, ", "))
else
client:ChatNotify("Vous avez retiré "..sc.." scrédits stérilisés à : "..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("Vous devez regarder une cible valable !")
return
end
local bIsRagdoll = target:GetClass() == "prop_ragdoll"
if (target:GetPos():DistToSqr(client:GetPos()) > 400 * 400) then
client:Notify("Votre cible est trop éloignée !")
return
end
if ((bIsRagdoll and !IsValid(target.ixPlayer)) or (!bIsRagdoll and !target:IsRestricted())) then
client:Notify("Votre cible doit être inconsciente ou attachée !")
return
end
if (bIsRagdoll) then
target = target.ixPlayer
end
target.beingAmputated = client
target.beingAmputatedEnd = CurTime() + 60
target.beingAmputatedReason = reason
client:Notify("Cible pour amputation ! Appliquez le verdict !")
end
})
ix.command.Add("SetCombineDoor", {
description = "Mettre une porte comme Combine.",
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("Définissez cette porte comme une porte de Combine.")
hook.Run("SaveDoorData")
end
end
})
function PLUGIN:CreateDiskNameRequest(currentName, itemID, password)
Derma_StringRequest("Définir le nom de la disquette", "Définissez le nom du disque.", currentName or "Disquette", 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("Ce disque est protégé par un mot de passe.", "Entrez-le.", "", 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().." a amputé "..victim:Name().." pour : "..(victim.beingAmputatedReason or "aucune raison donnée"))
end
end
victim.beingAmputated:Notify("Verdict délivré !")
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("Un disque est inséré dans cet ordinateur !") 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("Vous n'êtes pas devant un ordinateur !") return false end
if !IsValid(targetEnt) then client:Notify("Vous n'êtes pas devant un ordinateur !") return false end
local entClass = targetEnt:GetClass()
if (entClass != "ix_medical_computer" and entClass != "ix_computer") then client:Notify("Vous n'êtes pas devant un ordinateur !") return false end
if targetEnt.hasDiskInserted then client:Notify("Il y a déjà un disque dans cet ordinateur !") 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("Impossible de déposer le disque et de l'insérer.")
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("Mauvais mot de passe.")
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("Définissez le nom du disque sur "..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 != "Papier" 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("Impossible de trouver la personne à qui vous vouliez envoyer une lettre.") 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:// Sujet '" .. fromName1 .. "' a envoyé une lettre à '" .. toName .. "'", nil, client)
end
combineutilities:AddLog(client, logsT, genericT, "TERMINAL", nil, "LETTRE ENVOYÉE / REÇUE - "..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 != "Papier" 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", "Papier")
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("La lettre a été envoyée avec succès.")
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("La lettre a été envoyée avec succès.")
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("darkrp/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() .. " a crée une escouade " .. 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:// Escouade " .. index .. " réassigné en escouade " .. 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() .. " désigné comme LEADER de l'escouade " .. index .. "", 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:// Escouade " .. index .. " a été démantelée", 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() .. " s'est intégré dans l'escouade " .. 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() .. " s'est détaché de l'escouade " .. 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("Poste de Travail", "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 = "Entrer 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("You need to use one of the buttons!")
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:// Subject " .. string.upper("biotic asset identification card: #") .. genericData.cid .. " joined Work-Cycle")
else
ix.combineNotify:AddNotification("LOG:// Subject '" .. genericData.name .. "' joined Work-Cycle", 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,75 @@
--[[
| 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 = "Poste de Travail"
ENT.Base = "ix_terminal"
ENT.Author = "Fruity"
ENT.Contact = "Willard Networks"
ENT.Purpose = "Start and stop workshifts via an entity."
ENT.Instructions = "Appuyez sur E pour entrer votre CID. Appuyez sur le bouton pour pour démarrer ou stopper."
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.Displays = {
[1] = {"EN ATTENTE DE CID", Color( 255, 255, 180 ), true},
[2] = {"VÉRIFICATION", Color(255, 200, 0)},
[3] = {"DÉBUT DU TRAVAIL", Color(0, 255, 0)},
[4] = {"RECHARGEMENT", Color(255, 200, 0)},
[5] = {"HORS-LIGNE", Color(255, 0, 0), true},
[6] = {"SUCCÈS", Color( 0, 255, 180 )},
[7] = {"FIN DU TRAVAIL", Color(255, 0, 0)},
[8] = {"AUCUNE INFO.", Color(0, 255, 0)},
[9] = {"POSTE INACTIF", Color(255, 0, 0)},
[10] = {"DÉJÀ PARTICIPÉ", Color(255, 0, 0)},
[11] = {"INSCRIPTION INTERROMPUE", 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, "Session terminer", 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, "Session terminer", true, true)
PLUGIN:EditDatafile(client, file["genericdata"], true, true)
end
local couponCharacter = ix.char.loaded[genericID]
if couponCharacter and coupon != false then
if coupon == "20 CRÉDITS" then
couponCharacter:SetPurchasedItems("coupon_basic", 1)
elseif coupon == "35 CRÉDITS" 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