This commit is contained in:
lifestorm
2024-08-04 23:54:45 +03:00
parent 8064ba84d8
commit 6a58f406b1
7522 changed files with 4011896 additions and 15 deletions

View File

@@ -0,0 +1,104 @@
--[[
| 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
local LocalPlayer = LocalPlayer
local IsValid = IsValid
local draw = draw
function PLUGIN:HUDPaint(width, height, alpha)
if (!IsValid(LocalPlayer())) then
return
end
local character = LocalPlayer():GetCharacter()
if (character and IsValid(ix.gui.chat) and ix.gui.chat:IsVisible() and ix.gui.chat.bActive) then
local radioChannels = {}
--local quick = {}
for k in pairs(LocalPlayer():GetLocalVar("radioChannels", {})) do
--[[
local quickCom = LocalPlayer():HasQuickComms(k)
if (quickCom) then
quick[quickCom] = k
continue
end
--]]
radioChannels[#radioChannels + 1] = k
end
table.sort(radioChannels, ix.radio.sortFunc)
for k, v in ipairs(radioChannels) do
radioChannels[k] = ix.radio:FindByID(v).name
end
--[[
local seen = false
if (!table.IsEmpty(quick)) then
for i = 1, 5 do
if (!seen and !quick[i]) then
quick[i] = "none"
elseif (quick[i]) then
seen = true
quick[i] = ix.radio:FindByID(quick[i]).name
end
end
end
--]]
local channelsText = L("radioChannels")..": "..((#radioChannels > 0) and table.concat(radioChannels, ", ") or L("radioNone"))
--local quickText = L("quickChannels")..": "..((#quick > 0) and table.concat(quick, ", ") or L("radioNone"))
local currChannel = ix.radio:FindByID(character:GetRadioChannel())
local currentText = L("radioSpeaking")..": "..(currChannel and currChannel.name or L("radioNone"))
local x, y = ix.gui.chat:GetPos()
y = y - SScaleMin(20 / 3)
x = x + 10
draw.SimpleTextOutlined(currentText, "DebugFixedRadio",
x, y, Color(255, 255, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, Color(0, 0, 0))
--[[
if (#quick > 0) then
y = y - ScreenScale(20 / 3)
draw.SimpleTextOutlined(quickText, "DebugFixed",
x, y, Color(255, 255, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, Color(0, 0, 0))
end
--]]
if (#radioChannels > 0) then
y = y - SScaleMin(20 / 3)
draw.SimpleTextOutlined(channelsText, "DebugFixedRadio",
x, y, Color(255, 255, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, Color(0, 0, 0))
end
end
end
net.Receive("ixRadioChannels", function(len)
local id = net.ReadUInt(32)
local character = ix.char.loaded[id]
local channels = {}
local total = net.ReadUInt(16)
for _ = 1, total do
channels[#channels + 1] = net.ReadString()
end
character.vars.radioChannels = channels
end)
function PLUGIN:InitializedPlugins()
CHAT_RECOGNIZED["radio"] = true
CHAT_RECOGNIZED["radio_eavesdrop"] = true
CHAT_RECOGNIZED["radio_eavesdrop_yell"] = true
end

View File

@@ -0,0 +1,137 @@
--[[
| 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 = "Radio Base"
ITEM.category = "Radio"
ITEM.model = Model("models/deadbodies/dead_male_civilian_radio.mdl")
ITEM.description = "A shiny handheld radio with a frequency tuner."
ITEM.isRadio = true
-- Inventory drawing
if (CLIENT) then
function ITEM:PaintOver(item, w, h)
if (item:GetData("enabled")) then
surface.SetDrawColor(110, 255, 110, 100)
surface.DrawRect(w - 14, h - 14, 8, 8)
end
end
function ITEM:PopulateTooltip(tooltip)
if (self:GetData("enabled")) then
local name = tooltip:GetRow("name")
name:SetBackgroundColor(derma.GetColor("Success", tooltip))
end
local channel = ix.radio:FindByID(self:GetChannel())
if (channel) then
local chTip = tooltip:AddRowAfter("name", "channel")
chTip:SetText("Channel: "..channel.name)
chTip:SizeToContents()
end
end
end
function ITEM:GetChannel(bForce)
if (bForce or self:GetData("enabled")) then
return self.channel
else
return false
end
end
function ITEM:OnRemoved()
self:SetData("enabled", false)
local owner = self:GetOwner()
if (owner) then
ix.radio:RemoveListenerFromChannel(owner, self:GetChannel(true))
end
end
function ITEM:OnDestroyed(entity)
self:SetData("enabled", false)
if (IsValid(entity)) then
ix.radio:RemoveStationaryFromChannel(self:GetChannel(true), entity)
end
end
ITEM.functions.ToggleOn = {
name = "Toggle On",
OnRun = function(item)
item:SetData("enabled", true)
item.player:EmitSound("buttons/lever7.wav", 50, math.random(170, 180), 0.25)
item:SetData("volume", 0, nil, false)
if (!IsValid(item.entity)) then
local owner = item:GetOwner()
if (owner) then
ix.radio:AddListenerToChannel(owner, item:GetChannel())
end
else
ix.radio:AddStationaryToChannel(item:GetChannel(), item.entity)
end
return false
end,
OnCanRun = function(item)
return item:GetData("enabled", false) == false
end
}
ITEM.functions.ToggleOff = {
name = "Toggle Off",
OnRun = function(item)
item:SetData("enabled", false)
item.player:EmitSound("buttons/lever7.wav", 50, math.random(170, 180), 0.25)
if (!IsValid(item.entity)) then
local owner = item:GetOwner()
if (owner) then
ix.radio:RemoveListenerFromChannel(owner, item:GetChannel(true))
end
else
ix.radio:RemoveStationaryFromChannel(item:GetChannel(true), item.entity)
end
return false
end,
OnCanRun = function(item)
return item:GetData("enabled", false) == true
end
}
ITEM.functions.VolumeDown = {
name = "Volume Down",
OnRun = function(item)
item:SetData("volume", 0, nil, false)
ix.radio:RemoveStationaryFromChannel(item:GetChannel(), item.entity)
return false
end,
OnCanRun = function(item)
return IsValid(item.entity) and item:GetData("volume", 0) == 1 and item:GetData("enabled")
end
}
ITEM.functions.VolumeUp = {
name = "Volume Up",
OnRun = function(item)
item:SetData("volume", 1, nil, false)
ix.radio:AddStationaryToChannel(item:GetChannel(), item.entity)
return false
end,
OnCanRun = function(item)
return IsValid(item.entity) and item:GetData("volume", 0) == 0 and item:GetData("enabled")
end
}

View File

@@ -0,0 +1,106 @@
--[[
| 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 = "Radio (M) Base"
ITEM.category = "Radio"
ITEM.model = Model("models/deadbodies/dead_male_civilian_radio.mdl")
ITEM.description = "A shiny handheld radio with a frequency tuner."
ITEM.isRadio = true
-- Inventory drawing
if (CLIENT) then
function ITEM:PaintOver(item, w, h)
if (item:GetData("enabled")) then
surface.SetDrawColor(110, 255, 110, 100)
surface.DrawRect(w - 14, h - 14, 8, 8)
end
end
function ITEM:PopulateTooltip(tooltip)
if (self:GetData("enabled")) then
local name = tooltip:GetRow("name")
name:SetBackgroundColor(derma.GetColor("Success", tooltip))
end
local channels = self:GetChannels()
if (channels) then
local channelNames = {}
for k, v in ipairs(channels) do
if (ix.radio:FindByID(v)) then
channelNames[#channelNames + 1] = ix.radio:FindByID(v).name
end
end
local chTip = tooltip:AddRowAfter("name", "channel")
chTip:SetText("Channels: "..table.concat(channelNames, ", "))
chTip:SizeToContents()
end
end
end
function ITEM:GetChannels(bForce)
return {}
end
function ITEM:OnRemoved()
self:SetData("enabled", false)
local owner = self:GetOwner()
if (owner) then
for _, v in ipairs(self:GetChannels(true)) do
ix.radio:RemoveListenerFromChannel(owner, v)
end
end
end
function ITEM:OnDestroyed(entity)
self:SetData("enabled", false)
end
ITEM.functions.ToggleOn = {
name = "Toggle Radio On",
OnRun = function(item)
item:SetData("enabled", true)
item.player:EmitSound("buttons/lever7.wav", 50, math.random(170, 180), 0.25)
local owner = item:GetOwner()
if (owner) then
for _, v in ipairs(item:GetChannels()) do
ix.radio:AddListenerToChannel(owner, v)
end
end
return false
end,
OnCanRun = function(item)
return item:GetData("enabled", false) == false
end
}
ITEM.functions.ToggleOff = {
name = "Toggle Radio Off",
OnRun = function(item)
item:SetData("enabled", false)
item.player:EmitSound("buttons/lever7.wav", 50, math.random(170, 180), 0.25)
local owner = item:GetOwner()
if (owner) then
for _, v in ipairs(item:GetChannels(true)) do
ix.radio:RemoveListenerFromChannel(owner, v)
end
end
return false
end,
OnCanRun = function(item)
return item:GetData("enabled", false) == true
end
}

View File

@@ -0,0 +1,179 @@
--[[
| 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 = "Radio (M2) Base"
ITEM.model = Model("models/props_lab/citizenradio.mdl")
ITEM.description = "A big powerful long-range radio allowing for communication across large distances - or through thick obstructions."
ITEM.isRadio = true
ITEM.category = "Radio"
ITEM.height = 4
ITEM.width = 4
ITEM.maxFrequencies = 3
if (CLIENT) then
function ITEM:PaintOver(item, w, h)
if (item:GetData("enabled")) then
surface.SetDrawColor(110, 255, 110, 100)
surface.DrawRect(w - 14, h - 14, 8, 8)
end
end
function ITEM:PopulateTooltip(tooltip)
if (self:GetData("enabled")) then
local name = tooltip:GetRow("name")
name:SetBackgroundColor(derma.GetColor("Success", tooltip))
end
local channels = self:GetChannels()
if (channels) then
local channelNames = {}
for k, v in ipairs(channels) do
if (ix.radio:FindByID(v)) then
channelNames[#channelNames + 1] = ix.radio:FindByID(v).name
end
end
local chTip = tooltip:AddRowAfter("name", "channel")
chTip:SetText("Channels: "..table.concat(channelNames, ", "))
chTip:SizeToContents()
end
end
end
function ITEM:GetChannels(bForce)
if (bForce or self:GetData("enabled")) then
return self:GetData("channels", {})
else
return {}
end
end
function ITEM:OnRemoved()
self:SetData("enabled", false)
local owner = self:GetOwner()
if (owner) then
for _, v in ipairs(self:GetChannels(true)) do
ix.radio:RemoveListenerFromChannel(owner, v)
end
end
end
function ITEM:OnDestroyed(entity)
self:SetData("enabled", false)
end
ITEM.functions.setRadioFrequency = {
name = "Set Frequency",
icon = "icon16/transmit.png",
isMulti = true,
multiOptions = function(item, player)
local options = {}
for i = 1, item.maxFrequencies do
options[i] = {name = "Freq "..i, OnClick = function(itemTbl)
local freq = itemTbl:GetData("channels", {})[i]
local freqText = freq and string.match(freq, "^freq_(%d%d%d)$") or ""
Derma_StringRequest("Select Frequency", "Please enter the frequency you wish to switch to:", freqText, function(text)
local newFreq = tonumber(text)
if (string.len(text) == 2 and newFreq and newFreq >= 10) then
net.Start("ixInventoryAction")
net.WriteString("setRadioFrequency")
net.WriteUInt(itemTbl.id, 32)
net.WriteUInt(itemTbl.invID, 32)
net.WriteTable({i, text})
net.SendToServer()
else
player:Notify("Lütfen 100 ile 999 arasında bir frekans girin.")
end
end, nil, "Set", "Cancel")
return false
end}
end
return options
end,
OnRun = function(item, data)
if (!data or !data[1]) then return false end
if (data[1] < 1 or data[1] > item.maxFrequencies) then return false end
local newFreq = tonumber(data[2])
if (string.len(data[2]) != 2 or !newFreq or newFreq < 10) then return false end
local channels = item:GetData("channels", {})
local oldFreq = channels[data[1]]
channels[data[1]] = "freq_"..data[2]
item:SetData("channels", channels)
if (oldFreq) then
ix.radio:RemoveListenerFromChannel(item:GetOwner(), oldFreq)
end
ix.radio:AddListenerToChannel(item:GetOwner(), channels[data[1]])
return false
end,
OnCanRun = function(item)
if (IsValid(item.entity)) then return false end
return true
end
}
ITEM.functions.setRadioOn = {
name = "Toggle Radio On",
icon = "icon16/connect.png",
OnRun = function(item)
item:SetData("enabled", true)
item.player:EmitSound("buttons/lever7.wav", 50, math.random(170, 180), 0.25)
local owner = item:GetOwner()
if (owner) then
for _, v in ipairs(item:GetChannels()) do
ix.radio:AddListenerToChannel(owner, v)
end
end
return false
end,
OnCanRun = function(item)
return item:GetData("enabled", false) == false
end
}
ITEM.functions.setRadioOff = {
name = "Toggle Radio Off",
icon = "icon16/disconnect.png",
OnRun = function(item)
item:SetData("enabled", false)
item.player:EmitSound("buttons/lever7.wav", 50, math.random(170, 180), 0.25)
local owner = item:GetOwner()
if (owner) then
for _, v in ipairs(item:GetChannels(true)) do
ix.radio:RemoveListenerFromChannel(owner, v)
end
end
return false
end,
OnCanRun = function(item)
return item:GetData("enabled", false) == true
end
}
function ITEM:OnInstanced()
local tbl = {"freq_10"}
if (self.maxFrequencies > 1) then
for i = 1, self.maxFrequencies - 1 do
tbl[#tbl + 1] = "freq_1"..i
end
end
self:SetData("channels", tbl)
end

View File

@@ -0,0 +1,119 @@
--[[
| 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 = "El Telsizi"
ITEM.model = Model("models/willardnetworks/skills/handheld_radio.mdl")
ITEM.description = "Analog ve dijital frekansları destekleyen uygun şekilde yapılmış bir el telsizi."
function ITEM:OnInstanced()
self:SetData("qt", {{}, {}, {}})
self:UpdateChannel()
end
function ITEM:UpdateChannel()
local client = self:GetOwner()
local oldChannel = client and self:GetChannel()
local zone, channel = self:GetData("zone", 1), self:GetData("ch", 1)
local qt = self:GetData("qt")
self:SetData("channel", "freq_"..zone.."_"..channel.."_"..(qt[zone][channel] or channel))
if (client and self:GetChannel() != oldChannel) then
ix.radio:RemoveListenerFromChannel(client, oldChannel)
ix.radio:AddListenerToChannel(client, self:GetChannel())
end
end
function ITEM:GetChannel(bForce)
if (bForce or self:GetData("enabled")) then
return self:GetData("channel")
else
return false
end
end
ITEM.functions.zone = {
name = "Bölge Ayarla",
isMulti = true,
multiOptions = function(item, player)
local zones = {}
for i = 1, 3 do
zones[i] = {name = i, data = {i}}
end
return zones
end,
OnRun = function(item, data)
item:SetData("zone", data[1])
item:UpdateChannel()
return false
end,
OnCanRun = function(item)
return !IsValid(item.entity)
end
}
ITEM.functions.channel = {
name = "Kanal Ayarla",
isMulti = true,
multiOptions = function(item, player)
local channels = {}
for i = 1, 16 do
channels[i] = {name = i, data = {i}}
end
return channels
end,
OnRun = function(item, data)
item:SetData("ch", data[1])
item:UpdateChannel()
return false
end,
OnCanRun = function(item)
return !IsValid(item.entity)
end
}
ITEM.functions.qt = {
name = "QT/DQT Ayarla",
OnClick = function(item)
local zone, channel = item:GetData("zone", 1), item:GetData("ch", 1)
local max = zone == 1 and 16 or 99
local text = zone == 1 and "QT Tone" or "DQT Code"
local qt = item:GetData("qt")
Derma_StringRequest(text, "What would you like to set the "..text.." to? 1-"..max, qt[zone][channel] or channel,
function(newQT)
newQT = math.floor(tonumber(newQT))
if (newQT < 1 or newQT > max) then return end
net.Start("ixInventoryAction")
net.WriteString("qt")
net.WriteUInt(item.id, 32)
net.WriteUInt(item.invID, 32)
net.WriteTable({newQT})
net.SendToServer()
end)
end,
OnRun = function(item, data)
local qt = item:GetData("qt")
qt[item:GetData("zone", 1)][item:GetData("ch", 1)] = data[1]
item:SetData("qt", qt)
item:UpdateChannel()
return false
end,
OnCanRun = function(item)
return !IsValid(item.entity)
end
}

View File

@@ -0,0 +1,79 @@
--[[
| 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 = "Long-Range Radio"
ITEM.model = Model("models/props_lab/citizenradio.mdl")
ITEM.description = "A big powerful long-range radio allowing for communication across large distances - or through thick obstructions."
ITEM.height = 4
ITEM.width = 3
function ITEM:GetChannel(bForce)
if (bForce or self:GetData("enabled")) then
return self:GetData("channel", "freq_10")
else
return false
end
end
function ITEM:OnInstanced()
self:SetData("channel", "freq_11")
self:UpdateChannel("10")
end
function ITEM:UpdateChannel(newFreq)
local client = self:GetOwner()
local oldChannel = client and self:GetChannel()
self:SetData("channel", "freq_"..newFreq)
if (client and self:GetChannel() != oldChannel) then
ix.radio:RemoveListenerFromChannel(client, oldChannel)
ix.radio:AddListenerToChannel(client, self:GetChannel())
end
end
ITEM.functions.setRadioFrequency = {
name = "Set Frequency",
icon = "icon16/transmit.png",
OnClick = function(item)
local freq = item:GetChannel(true)
local freqText = freq and string.match(freq, "^freq_(%d%d)$") or ""
Derma_StringRequest("Select Frequency", "Please enter the frequency you wish to switch to:", freqText, function(text)
local newFreq = tonumber(text)
if (string.len(text) == 2 and newFreq and newFreq >= 10) then
net.Start("ixInventoryAction")
net.WriteString("setRadioFrequency")
net.WriteUInt(item.id, 32)
net.WriteUInt(item.invID, 32)
net.WriteTable({text})
net.SendToServer()
elseif (IsValid (item.player)) then
item.player:Notify("Lütfen 10 ile 99 arasında bir frekans girin.")
end
end)
return false
end,
OnRun = function(item, data)
if (!data or !data[1]) then return false end
local newFreq = tonumber(data[1])
if (string.len(data[1]) != 2 or !newFreq or newFreq < 10) then return false end
item:UpdateChannel(data[1])
return false
end,
OnCanRun = function(item)
if (IsValid(item.entity)) then return false end
return true
end
}

View File

@@ -0,0 +1,96 @@
--[[
| 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 = "Eski El Telsizi"
ITEM.model = Model("models/willardnetworks/skills/handheld_radio.mdl")
ITEM.description = "Sadece analog frekansları destekleyen geçici radyo."
function ITEM:OnInstanced()
self:SetData("qt", {})
self:UpdateChannel()
end
function ITEM:UpdateChannel()
local client = self:GetOwner()
local oldChannel = client and self:GetChannel()
local channel = self:GetData("ch", 1)
local qt = self:GetData("qt")
self:SetData("channel", "freq_1_"..channel.."_"..(qt[channel] or channel))
if (client and self:GetChannel() != oldChannel) then
ix.radio:RemoveListenerFromChannel(client, oldChannel)
ix.radio:AddListenerToChannel(client, self:GetChannel())
end
end
function ITEM:GetChannel(bForce)
if (bForce or self:GetData("enabled")) then
return self:GetData("channel")
else
return false
end
end
ITEM.functions.channel = {
name = "Set Channel",
isMulti = true,
multiOptions = function(item, player)
local channels = {}
for i = 1, 16 do
channels[i] = {name = i, data = {i}}
end
return channels
end,
OnRun = function(item, data)
item:SetData("ch", data[1])
item:UpdateChannel()
return false
end,
OnCanRun = function(item)
return !IsValid(item.entity)
end
}
ITEM.functions.qt = {
name = "Set QT",
OnClick = function(item)
local channel = item:GetData("ch", 1)
local text = "QT Tone"
local qt = item:GetData("qt")
Derma_StringRequest(text, "What would you like to set the "..text.." to? 1-16", qt[channel] or channel,
function(newQT)
newQT = math.floor(tonumber(newQT))
if (newQT < 1 or newQT > 16) then return end
net.Start("ixInventoryAction")
net.WriteString("qt")
net.WriteUInt(item.id, 32)
net.WriteUInt(item.invID, 32)
net.WriteTable({newQT})
net.SendToServer()
end)
end,
OnRun = function(item, data)
local qt = item:GetData("qt")
qt[item:GetData("ch", 1)] = data[1]
item:SetData("qt", qt)
item:UpdateChannel()
return false
end,
OnCanRun = function(item)
return !IsValid(item.entity)
end
}

View File

@@ -0,0 +1,18 @@
--[[
| 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 = "Multi-Channel Long-Range Radio"
ITEM.model = Model("models/props_lab/citizenradio.mdl")
ITEM.description = "A big powerful long-range radio allowing for communication across large distances - or through thick obstructions. It has multiple channels"
ITEM.category = "Radio"
ITEM.height = 4
ITEM.width = 4

View File

@@ -0,0 +1,221 @@
--[[
| 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 ix = ix
ix.radio = ix.radio or {}
ix.radio.channels = ix.radio.channels or {}
ix.radio.types = {}
ix.radio.types.whisper = 1
ix.radio.types.talk = 2
ix.radio.types.yell = 3
ix.radio.types.scream = 4
local ipairs = ipairs
local istable = istable
local table = table
function ix.radio:RegisterChannel(uniqueID, data)
if (self.channels[uniqueID]) then
return
end
if (!istable(data)) then
ErrorNoHalt("[IX: Radio] Attempted to register channel \"" .. uniqueID .. "\" with invalid data.")
return
end
data.uniqueID = uniqueID
data.name = data.name or uniqueID
if (!data.color) then
data.color = Color(96, 179, 0, 255)
end
data.listeners = {}
data.listenersByKeys = {}
data.stationaries = {}
data.priority = data.priority or 0
if (data.icon and isstring(data.icon)) then
data.icon = ix.util.GetMaterial(data.icon)
end
self.channels[uniqueID] = data
if (data.shortcutCommand) then
local sc = data.shortcutCommand
local a = string.sub(sc, 1, 1)
ix.command.Add(sc.."Radio", {
alias = {a, data.alias},
arguments = ix.type.text,
OnCheckAccess = function(_, client)
return client:GetCharacter() and ix.radio:CharacterHasChannel(client:GetCharacter(), uniqueID)
end,
OnRun = function(_, client, text)
return ix.radio:SayOnRadio(client, text, ix.radio.types.talk, uniqueID)
end
})
ix.command.Add(sc.."Whisper", {
alias = {a.."W", (data.alias or a).."W"},
arguments = ix.type.text,
OnCheckAccess = function(_, client)
return client:GetCharacter() and ix.radio:CharacterHasChannel(client:GetCharacter(), uniqueID)
end,
OnRun = function(_, client, text)
return ix.radio:SayOnRadio(client, text, ix.radio.types.whisper, uniqueID)
end,
})
ix.command.Add(sc.."Yell", {
alias = {a.."Y", (data.alias or a).."Y"},
arguments = ix.type.text,
OnCheckAccess = function(_, client)
return client:GetCharacter() and ix.radio:CharacterHasChannel(client:GetCharacter(), uniqueID)
end,
OnRun = function(_, client, text)
return ix.radio:SayOnRadio(client, text, ix.radio.types.yell, uniqueID)
end,
})
end
return data
end
function ix.radio:RemoveChannel(uniqueID)
self.channels[uniqueID] = nil
end
function ix.radio:FindByID(channelID)
if (!channelID or channelID == "") then return end
if (self.channels[channelID]) then
return self.channels[channelID]
else
local zone, channel, qt = string.match(channelID, "^freq_(%d)_(%d?%d)_(%d?%d)$")
if (zone and channel and qt) then
local qtText = zone == "1" and " QT" or " DQT"
self:RegisterChannel(channelID, {
name = zone.."-"..channel..qtText..qt,
icon = "willardnetworks/chat/radio_icon.png"
})
return self.channels[channelID]
end
local freq = string.match(channelID, "^freq_(%d%d)$")
if (freq and tonumber(freq) and tonumber(freq) >= 10) then
self:RegisterChannel(channelID, {
name = freq,
icon = "willardnetworks/chat/radio_icon.png",
backpackRadio = true
})
return self.channels[channelID]
end
end
end
function ix.radio.sortFunc(a, b)
a, b = ix.radio:FindByID(a), ix.radio:FindByID(b)
if (!a) then
return false
elseif (!b) then
return true
elseif (a.priority != b.priority) then
return a.priority > b.priority
else
return a.name < b.name
end
end
function ix.radio:GetAllChannelsFromChar(character)
local channels = table.Copy(character:GetRadioChannels())
local inventory = character:GetInventory()
local items = inventory:GetItems()
for _, item in pairs(items) do
if (item.isRadio) then
if (item.GetChannels) then
for _, v in ipairs(item:GetChannels()) do
channels[#channels + 1] = v
end
elseif (item.GetChannel and item:GetChannel()) then
channels[#channels + 1] = item:GetChannel()
end
end
end
local faction = ix.faction.indices[character:GetFaction()]
if (faction and istable(faction.radioChannels)) then
for _, channel in ipairs(faction.radioChannels) do
channels[#channels + 1] = channel
end
end
hook.Run("AdjustCharacterRadioChannels", character, channels)
local seen = {}
for i = #channels, 1, -1 do
if (seen[channels[i]]) then
table.remove(channels, i)
else
seen[channels[i]] = true
end
end
table.sort(channels, ix.radio.sortFunc)
return channels
end
function ix.radio:CharacterHasChannel(character, channelID)
local channel = self:FindByID(channelID)
if (!channel) then return false end
channelID = channel.uniqueID
local faction = ix.faction.indices[character:GetFaction()]
if (faction and istable(faction.radioChannels)) then
for _, chnlID in ipairs(faction.radioChannels) do
if (chnlID == channelID) then
return true
end
end
end
local inventory = character:GetInventory()
local items = inventory:GetItems()
for _, item in pairs(items) do
if (item.isRadio) then
if (item.GetChannels) then
for _, v in ipairs(item:GetChannels()) do
if (v == channelID) then
return true
end
end
elseif (item:GetChannel() == channelID) then
return true
end
end
end
local channels = character:GetRadioChannels()
for _, chnl in ipairs(channels) do
if (chnl == channelID) then
return true
end
end
return hook.Run("HasCharacterRadioChannel", character, channelID)
end

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/
--]]
local PLAYER = FindMetaTable("Player")
function PLAYER:GetQuickComms(number)
local character = self:GetCharacter()
if (!character) then return false end
local items = character:GetInventory():GetItems()
for k, v in pairs(items) do
if (!v.isRadio or !v.isIFF) then continue end
local channels = v:GetChannels()
if (table.IsEmpty(channels)) then continue end
if (channels[number]) then
return channels[number]
else
return false
end
end
return false
end
function PLAYER:HasQuickComms(channel)
local character = self:GetCharacter()
if (!character) then return false end
local items = character:GetInventory():GetItems()
for k, v in pairs(items) do
if (!v.isRadio or !v.isIFF) then continue end
local channels = v:GetChannels()
if (table.IsEmpty(channels)) then continue end
for k1, v1 in ipairs(channels) do
if (v1 == channel) then
return k1
end
end
return false
end
return false
end

View File

@@ -0,0 +1,80 @@
--[[
| 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.radio:RegisterChannel("cmb", {
name = "CMB",
color = Color(180, 226, 226, 255),
icon = "willardnetworks/chat/cmb_shared_icon.png",
--shortcutCommand = "Cmb" --automatically create commands to radio on this channel without switching to it
})
ix.radio:RegisterChannel("cca", {
name = "CCA",
color = Color(151, 161, 255, 255),
icon = "willardnetworks/chat/ca_radio_icon.png",
priority = 1
})
ix.radio:RegisterChannel("cmru", {
name = "CMRU",
color = Color(151, 161, 255, 255),
icon = "willardnetworks/chat/ca_radio_icon.png",
priority = 1
})
ix.radio:RegisterChannel("tac-3", {
name = "TAC-3",
color = Color(81, 208, 231, 255),
icon = "willardnetworks/chat/cp_radio_icon.png",
priority = 1
})
ix.radio:RegisterChannel("tac-4", {
name = "TAC-4",
color = Color(255, 89, 0, 255),
icon = "willardnetworks/chat/cp_radio_icon.png",
priority = 1
})
ix.radio:RegisterChannel("tac-5", {
name = "TAC-5",
color = Color(237, 222, 59, 255),
icon = "willardnetworks/chat/dispatch_icon.png",
priority = 0
})
ix.radio:RegisterChannel("ota-tac", {
name = "OTA-TAC",
color = Color(222, 33, 33, 255),
icon = "willardnetworks/chat/dispatch_icon.png",
priority = 2
})
ix.radio:RegisterChannel("cwu", {
name = "CWU",
color = Color(151, 161, 255, 255),
icon = "willardnetworks/chat/ca_radio_icon.png",
priority = 1
})
ix.radio:RegisterChannel("mcp", {
name = "MCP",
color = Color(165,50,50),
icon = "willardnetworks/chat/ca_radio_icon.png",
priority = 2
})
ix.radio:RegisterChannel("ccr-tac", {
name = "CCR-TAC",
color = Color(35, 194, 80, 255),
icon = "willardnetworks/chat/ca_radio_icon.png",
priority = 2
})

View File

@@ -0,0 +1,192 @@
--[[
| 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.command.Add("CharAddRadioChannel", {
description = "@cmdCharAddRadioChannel",
privilege = "Manage Radio",
arguments = {
ix.type.player,
ix.type.string
},
OnRun = function(self, client, target, channelID)
local channel = ix.radio:FindByID(channelID)
if (channel) then
ix.radio:AddPlayerChannelSubscription(target, channel.uniqueID)
client:NotifyLocalized("radioSubbed", target:Name(), channel.name)
target:NotifyLocalized("radioSubbedT", channel.name, client:Name())
else
return "@radioChannelNotExist"
end
end
})
ix.command.Add("CharRemoveRadioChannel", {
description = "@cmdCharRemoveRadioChannel",
privilege = "Manage Radio",
arguments = {
ix.type.player,
ix.type.string
},
OnRun = function(self, client, target, channelID)
local channel = ix.radio:FindByID(channelID)
if (channel) then
ix.radio:RemovePlayerChannelSubscription(target, channel.uniqueID)
client:NotifyLocalized("radioUnsubbed", target:Name(), channel.name)
target:NotifyLocalized("radioUnsubbedT", channel.name, client:Name())
else
return "@radioChannelNotExist"
end
end
})
ix.command.Add("SC", {
description = "@cmdSC",
alias = "SetChannel",
arguments = ix.type.text,
privilege = "Radio Use",
OnRun = function(self, client, text)
text = text:Trim()
local character = client:GetCharacter()
local channels = ix.radio:GetAllChannelsFromChar(character)
for _, v in ipairs(channels) do
if (v == text) then
character:SetRadioChannel(v)
client:NotifyLocalized("radioSetChannel", v)
return
end
end
local shortest = nil
for _, v in ipairs(channels) do
local channel = ix.radio:FindByID(v)
if (string.find(v, text, 1, true)
or string.find(channel.name, text, 1, true)) then
if (!shortest or string.utf8len(shortest) > string.utf8len(v)) then
shortest = channel.uniqueID
end
end
end
local channel = ix.radio:FindByID(shortest)
if (channel) then
character:SetRadioChannel(channel.uniqueID)
client:NotifyLocalized("radioSetChannel", channel.name)
return
end
client:NotifyLocalized("radioChannelNotExist")
end,
})
ix.command.Add("Radio", {
alias = "R",
arguments = ix.type.text,
privilege = "Radio Use",
combineBeep = true,
OnRun = function(self, client, text)
return ix.radio:SayOnRadio(client, text, ix.radio.types.talk)
end
})
ix.command.Add("RadioWhisper", {
alias = "RW",
arguments = ix.type.text,
privilege = "Radio Use",
combineBeep = true,
OnRun = function(self, client, text)
return ix.radio:SayOnRadio(client, text, ix.radio.types.whisper)
end,
})
ix.command.Add("RadioYell", {
alias = "RY",
arguments = ix.type.text,
privilege = "Radio Use",
combineBeep = true,
OnRun = function(self, client, text)
return ix.radio:SayOnRadio(client, text, ix.radio.types.yell)
end,
})
--[[
Quick comm radio stuff - we don't use this but leaving it here
for i = 1, 5 do
ix.command.Add("Com"..i, {
alias = "R"..i,
arguments = ix.type.text,
OnCheckAccess = function(self, client)
return client:GetQuickComms(i) and CAMI.PlayerHasAccess(client, "Helix - Radio Use")
end,
OnRun = function(self, client, text)
local character = client:GetCharacter()
if (!character) then return end
if (ix.radio:CharacterHasChannel(character, client:GetQuickComms(i))) then
return ix.radio:SayOnRadio(client, text, ix.radio.types.talk, client:GetQuickComms(i))
end
return "You do not have any quick comms channels!"
end,
})
ix.command.Add("Com"..i.."Whisper", {
alias = {"Com"..i.."W", "R"..i.."W"},
arguments = ix.type.text,
OnCheckAccess = function(self, client)
return client:GetQuickComms(i) and CAMI.PlayerHasAccess(client, "Helix - Radio Use")
end,
OnRun = function(self, client, text)
local character = client:GetCharacter()
if (!character) then return end
if (ix.radio:CharacterHasChannel(character, client:GetQuickComms(i))) then
return ix.radio:SayOnRadio(client, text, ix.radio.types.whisper, client:GetQuickComms(i))
end
return "You do not have any quick comms channels!"
end,
})
ix.command.Add("Com"..i.."Yell", {
alias = {"Com"..i.."Y", "R"..i.."Y"},
arguments = ix.type.text,
OnCheckAccess = function(self, client)
return client:GetQuickComms(i) and CAMI.PlayerHasAccess(client, "Helix - Radio Use")
end,
OnRun = function(self, client, text)
local character = client:GetCharacter()
if (!character) then return end
if (ix.radio:CharacterHasChannel(character, client:GetQuickComms(i))) then
return ix.radio:SayOnRadio(client, text, ix.radio.types.yell, client:GetQuickComms(i))
end
return "You do not have any quick comms channels!"
end,
})
ix.option.Add("com"..i.."Color", ix.type.color, Color(200,200,255,255), {
category = "chat",
hidden = function()
return !CAMI.PlayerHasAccess(LocalPlayer(), "Helix - Radio Use") or !LocalPlayer():GetQuickComms(i)
end
})
ix.lang.AddTable("english", {
["optCom"..i.."Color"] = "Set Com"..i.." Color",
["optdCom"..i.."Color"] = "Set the color of radio messages received on the 'Freq "..i.."' frequency of your radio."
})
end
--]]

View File

@@ -0,0 +1,259 @@
--[[
| 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
local IsValid = IsValid
local hook = hook
PLUGIN.name = "Radio Redux"
PLUGIN.author = "Gr4Ss"
PLUGIN.description = "Implements a better functional radio system. Based on my CW Radio Redux plugin. Credits to SleepyMode for the initial port (which this is very loosely based on)."
CAMI.RegisterPrivilege({
Name = "Helix - Manage Radio",
MinAccess = "admin",
Description = "Manually assign radio channels to players."
})
CAMI.RegisterPrivilege({
Name = "Helix - Radio Use",
MinAccess = "user",
Description = "Use the basic radio commands."
})
ix.char.RegisterVar("radioChannel", {
default = "",
field = "radiochannel",
fieldType = ix.type.string,
isLocal = true,
bNoDisplay = true
})
ix.config.Add("radioLimitRange", 0, "Limit the range of regular handheld radios.", nil, {
data = {min = 0, max = 25000},
category = "Miscellaneous"
})
ix.config.Add("radioHideWhisper", true, "Do not give the actual text for radio whispers.", nil, {
category = "Miscellaneous"
})
ix.lang.AddTable("english", {
radioFormat = "[%s] %s%s: \"%s\"",
radioWhisper = " fısıldıyor",
radioYell = " bağırıyor",
radioScream = " ÇIĞLIK ATIYOR",
radioEaves = " konuşuyor ",
radioEavesW = " fısıldıyor ",
radioEavesY = " bağırıyor ",
radioEavesSc = " ÇIĞLIK ATIYOR ",
radioHis = "onun",
radioHer = "onun",
radioRadio = "radyo",
radioStationary = "sabit bir radyo",
radioYellOver = " radyo üzerinden bağırıyor",
radioScreamOver = " radyo üzerinden ÇIĞLIK ATIYOR",
radioChannels = "Radyo kanalları",
quickChannels = "Hızlı kanallar",
radioSpeaking = "Konuşulan kanal",
radioNone = "yok",
radioSetChannel = "Kanalınızı \"%s\" olarak ayarladınız.",
radioChannelNotExist = "Bu kanal mevcut değil!",
radioSubbed = "%s kişisini '%s' kanalına abone ettiniz.",
radioSubbedT = "%s tarafından '%s' kanalına abone edildiniz.",
radioUnsubbed = "%s kişisini '%s' kanalından çıkardınız.",
radioUnsubbedT = "%s tarafından '%s' kanalından çıkartıldınız.",
radioNotOn = "Bu radyo açık değil!",
radioTooFar = "Bu sabit radyo çok uzakta!",
radioInvalidChannel = "Geçerli bir radyo kanalında konuşmalısınız!",
cmdCharAddRadioChannel = "Bir oyuncuyu bir radyo kanalına abone eder.",
cmdCharRemoveRadioChannel = "Bir oyuncuyu bir radyo kanalından çıkarır.",
cmdSC = "Konuşmak istediğiniz kanalı seçin.",
})
ix.lang.AddTable("spanish", {
radioNotOn = "¡Esta radio no está encendida!",
radioFormat = "[%s] %s%s: \"%s\"",
radioRadio = "radio",
radioWhisper = " susurra",
radioSpeaking = "Hablando en",
radioScreamOver = " CHILLA por la radio",
radioInvalidChannel = "¡Debes hablar en un canal de radio válido!",
radioSetChannel = "Has establecido tu canal a \"%s\".",
cmdSC = "Elige el Canal en el que quieres hablar.",
radioYell = " grita",
radioChannels = "Canales de radio",
radioChannelNotExist = "¡Este canal no existe!",
radioScream = " CHILLA",
radioStationary = "una radio fija",
cmdCharRemoveRadioChannel = "Anula la suscripción de un jugador a un canal de radio.",
cmdCharAddRadioChannel = "Suscribe a un jugador a un canal de radio.",
radioUnsubbedT = "Has sido dado de baja del canal '%s' por %s.",
radioTooFar = "¡Esta radio fija está demasiado lejos!",
radioSubbedT = "Has sido suscrito al canal '%s' por %s.",
radioEaves = " habla hacia su ",
radioHis = "su",
radioEavesY = " grita a su ",
radioEavesW = " suspira a su ",
radioSubbed = "Has suscrito a %s al canal '%s'.",
radioHer = "su",
radioEavesSc = " CHILLA en su ",
radioNone = "ninguno",
radioYellOver = " grita por la radio",
radioUnsubbed = "Has cancelado la suscripción de %s al canal '%s'."
})
ix.char.RegisterVar("radioChannels", {
default = {},
field = "radiochannels",
fieldType = ix.type.text,
bNoDisplay = true,
isLocal = true,
OnSet = function(character, channelID, bRemove)
local channel = ix.radio:FindByID(channelID)
if (!channel) then return end
local channels = character:GetRadioChannels()
channelID = channel.uniqueID
if (!bRemove) then
for _, v in ipairs(channels) do
if v == channelID then
return
end
end
channels[#channels + 1] = channelID
else
local removed = false
for k, v in ipairs(channels) do
if v == channelID then
removed = true
table.remove(channels, k)
break
end
end
if (!removed) then return end
end
table.sort(channels)
character.vars.radioChannels = channels
net.Start("ixRadioChannels")
net.WriteUInt(character:GetID(), 32)
net.WriteUInt(#channels, 16)
for _, v in ipairs(channels) do
net.WriteString(v)
end
net.Send(character:GetPlayer())
end,
OnGet = function(character)
return character.vars.radioChannels or {}
end
})
--ix.util.Include("meta/sh_player.lua")
ix.util.Include("cl_hooks.lua")
ix.util.Include("sv_hooks.lua")
ix.util.Include("sv_plugin.lua")
ix.util.Include("sh_channels.lua")
ix.util.Include("sh_commands.lua")
do
local types = {
[ix.radio.types.talk] = "",
[ix.radio.types.whisper] = "radioWhisper",
[ix.radio.types.yell] = "radioYell",
[ix.radio.types.scream] = "radioScream",
}
local CLASS = {}
CLASS.indicator = "chatRadio"
if (CLIENT) then
function CLASS:OnChatAdd(speaker, text, anonymous, data)
local name = anonymous and L"someone" or
hook.Run("GetCharacterName", speaker, "radio") or
(IsValid(speaker) and speaker:Name() or "Console")
local rtext = L(types[data.radioType] or "")
local channel = ix.radio:FindByID(data.channel)
local rText = L("radioFormat", channel.name, name, rtext, text)
--local quickCom = LocalPlayer():HasQuickComms(data.channel)
local color = (quickCom and ix.option.Get("com"..quickCom.."Color")) or channel.color
if (channel.icon) then
chat.AddText(channel.icon, color, rText)
else
chat.AddText(color, rText)
end
end
end
ix.chat.Register("radio", CLASS)
end
do
local types = {
[ix.radio.types.talk] = "radioEaves",
[ix.radio.types.whisper] = "radioEavesW",
[ix.radio.types.yell] = "radioEavesY",
[ix.radio.types.scream] = "radioEavesSc",
}
local CLASS = {}
if (CLIENT) then
function CLASS:OnChatAdd(speaker, text, anonymous, data)
local name = anonymous and L"someone" or
hook.Run("GetCharacterName", speaker, "radio_eavesdrop") or
(IsValid(speaker) and speaker:Name() or "Console")
local rtext = L(types[data.radioType] or "")
if (!data.stationary) then
local genderText = L("radioHis")
if (speaker:IsFemale()) then
genderText = L("radioHer")
end
if (!ix.config.Get("radioHideWhisper") or data.radioType != ix.radio.types.whisper) then
chat.AddText(ix.chat.classes.ic.color, name, rtext, genderText, " ", L("radioRadio"), ": \"", text, "\"")
else
chat.AddText(ix.chat.classes.ic.color, name, rtext, genderText, " ", L("radioRadio"), ".")
end
else
if (!ix.config.Get("radioHideWhisper") or speaker == LocalPlayer() or data.radioType != ix.radio.types.whisper) then
chat.AddText(ix.chat.classes.ic.color, name, rtext, L("radioStationary"), ": \"", text, "\"")
else
chat.AddText(ix.chat.classes.ic.color, name, rtext, L("radioStationary"), ".")
end
end
end
end
ix.chat.Register("radio_eavesdrop", CLASS)
end
do
local CLASS = {}
if (CLIENT) then
function CLASS:OnChatAdd(speaker, text, anonymous, data)
local name = anonymous and L"someone" or
hook.Run("GetCharacterName", speaker, "radio_eavesdrop_yell") or
(IsValid(speaker) and speaker:Name() or "Console")
chat.AddText(ix.chat.classes.ic.color, name, L(data.radioType == ix.radio.types.yell and "radioYellOver" or "radioScreamOver"), ": \"", text, "\"")
end
end
ix.chat.Register("radio_eavesdrop_yell", CLASS)
end

View File

@@ -0,0 +1,116 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLUGIN = PLUGIN
function PLUGIN:PlayerDisconnected(client)
for _, channel in pairs(ix.radio.channels) do
if (channel.listenersByKeys[client]) then
local key = channel.listenersByKeys[client]
channel.listeners[key] = channel.listeners[#channel.listeners]
channel.listenersByKeys[channel.listeners[key]] = key
channel.listeners[#channel.listeners] = nil
channel.listenersByKeys[client] = nil
end
end
end
function PLUGIN:PrePlayerLoadedCharacter(client, character, lastChar)
client:SetLocalVar("radioChannels", {})
for _, channel in pairs(ix.radio.channels) do
if (channel.listenersByKeys[client]) then
local key = channel.listenersByKeys[client]
channel.listeners[key] = channel.listeners[#channel.listeners]
channel.listenersByKeys[channel.listeners[key]] = key
channel.listeners[#channel.listeners] = nil
channel.listenersByKeys[client] = nil
end
end
end
function PLUGIN:PlayerLoadedCharacter(client, character, lastChar)
local currChannel = character:GetRadioChannel()
if (!ix.radio:FindByID(currChannel) or !ix.radio:CharacterHasChannel(character, currChannel)) then
character:SetRadioChannel("")
end
local channels = ix.radio:GetAllChannelsFromChar(character)
for _, v in ipairs(channels) do
ix.radio:AddListenerToChannel(client, v)
end
if (!character.vars.radioChannels) then
character.vars.radioChannels = {}
net.Start("ixRadioChannels")
net.WriteUInt(character:GetID(), 32)
net.WriteUInt(#channels, 16)
for _, v in ipairs(channels) do
net.WriteString(v)
end
net.Send(character:GetPlayer())
end
end
function PLUGIN:OnItemTransferred(item, oldInv, newInv)
if (!item.isRadio) then return end
local oldID, newID = oldInv:GetID(), newInv:GetID()
if (oldID == newID) then return end
local oldOwner = oldID != 0 and !oldInv.vars.isStash and oldInv:GetOwner()
local newOwner = newID != 0 and !newInv.vars.isStash and newInv:GetOwner()
if (oldOwner and newOwner and oldOwner == newOwner) then return end
if (oldOwner and IsValid(oldOwner)) then
if (item.GetChannels) then
for _, v in ipairs(item:GetChannels(true)) do
ix.radio:RemoveListenerFromChannel(oldOwner, v)
end
elseif (item.GetChannel and item:GetChannel(true)) then
ix.radio:RemoveListenerFromChannel(oldOwner, item:GetChannel())
end
else
local channel = item.GetChannel and item:GetChannel(true)
if (channel) then
ix.radio:CleanStationariesFromChannel(channel)
end
end
if (newOwner and IsValid(newOwner)) then
if (item.GetChannels) then
for _, v in ipairs(item:GetChannels()) do
ix.radio:AddListenerToChannel(newOwner, v)
end
elseif (item.GetChannel and item:GetChannel()) then
ix.radio:AddListenerToChannel(newOwner, item:GetChannel())
end
end
end
function PLUGIN:InventoryItemAdded(oldInv, newInv, item)
if (oldInv or !item.isRadio) then return end
local newID = newInv:GetID()
if (newID == 0) then return end
local newOwner = newInv:GetOwner()
if (IsValid(newOwner)) then
if (item.GetChannels) then
for _, v in ipairs(item:GetChannels()) do
ix.radio:AddListenerToChannel(newOwner, v)
end
elseif (item.GetChannel and item:GetChannel()) then
ix.radio:AddListenerToChannel(newOwner, item:GetChannel())
end
end
end

View File

@@ -0,0 +1,293 @@
--[[
| 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 ipairs = ipairs
local IsValid = IsValid
local table = table
util.AddNetworkString("ixRadioChannels")
function ix.radio:SayOnRadio(speaker, text, radioType, channelID)
if (!speaker:Alive() or speaker:IsRestricted() or !speaker:GetCharacter()) then
speaker:NotifyLocalized("notNow")
return
end
local entity = speaker:GetEyeTraceNoCursor().Entity
local data = {radioType = radioType, channel = channelID}
if (!channelID and IsValid(entity) and entity:GetClass() == "ix_item") then
local item = ix.item.instances[entity.ixItemID]
if (item and item.isRadio) then
if (!item:GetData("enabled")) then
speaker:NotifyLocalized("radioNotOn")
return
end
local range = radioType == self.types.whisper and math.pow(ix.config.Get("chatRange", 280) * 0.25, 2) or 10000
if (entity:GetPos():DistToSqr(speaker:EyePos()) < range) then
data.channel = item:GetChannel()
data.stationary = true
else
speaker:NotifyLocalized("radioTooFar")
return
end
end
end
if (!data.channel) then
data.channel = speaker:GetCharacter():GetRadioChannel()
end
local result, reason = hook.Run("CanPlayerSayRadio", speaker, text, data)
if (result != nil) then
if (reason) then
speaker:Notify(reason)
end
return result
end
local channel = self:FindByID(data.channel)
if (!channel) then
speaker:Notify("radioInvalidChannel")
return
end
if (radioType == self.types.yell) then
local filtered = string.gsub(text, "[^%a]", "")
local length = string.len(filtered)
local capsLength = string.len(string.gsub(filtered, "[^%u]", ""))
if (capsLength / length > 0.9 and length >= 15) then
radioType = self.types.scream
data.radioType = radioType
end
end
local range = ix.config.Get("chatRange", 280)
if (radioType == self.types.whisper) then
range = range * 0.5
elseif (radioType >= self.types.yell) then
range = range * 2
end
range = range * range
if (!speaker:GetActiveCombineSuit()) then
speaker:EmitSound("willardnetworks/radio/handheld/handheld" .. math.random(1, 4) .. ".wav", 75)
end
local speakerEyePos = speaker:EyePos()
local bStationaries = #channel.stationaries > 0
local listeners, listenersByKeys
if (ix.config.Get("radioLimitRange", 0) > 0) then
local channelListeners = channel.listeners
listeners, listenersByKeys = {}, {}
for i = #channelListeners, 1, -1 do
local client = channelListeners[i]
if (channel.backpackRadio or client:TestPVS(speaker) or ((client:EyePos():DistToSqr(speakerEyePos) / ((channel.rangeMultiplier or 1) ^ 2)) < (ix.config.Get("radioLimitRange") ^ 2))) then
listeners[#listeners + 1] = client
listenersByKeys[client] = true
end
end
else
listeners = bStationaries and table.Copy(channel.listeners) or channel.listeners
listenersByKeys = channel.listenersByKeys
end
local eavesdrop = speaker:GetMoveType() != MOVETYPE_NOCLIP and {}
local yellEavesDrop = radioType >= self.types.yell and {}
for _, client in ipairs(player.GetAll()) do
if (!client:Alive()) then
continue
end
if (listenersByKeys[client]) then
continue
end
local clientEyePos = client:EyePos()
if (bStationaries) then
local bFound = false
for i = #channel.stationaries, 1, -1 do
local stationary = channel.stationaries[i]
if (!IsValid(stationary)) then
table.remove(channel.stationaries, i)
continue
end
if (stationary:GetPos():DistToSqr(clientEyePos) <= range) then
bFound = true
listeners[#listeners + 1] = client
break
end
end
if (bFound) then continue end
end
if (eavesdrop and speakerEyePos:DistToSqr(clientEyePos) <= range) then
eavesdrop[#eavesdrop + 1] = client
continue
end
if (channel.backpackRadio) then
local bAdd = false
for listener, _ in pairs(listenersByKeys) do
if (listener:GetMoveType() == MOVETYPE_NOCLIP and !listener:InVehicle()) then continue end
if (listener:EyePos():DistToSqr(clientEyePos) <= range) then
bAdd = true
break
end
end
if (bAdd) then
eavesdrop[#eavesdrop + 1] = client
continue
end
end
if (yellEavesDrop) then
-- potential yell eavesdropper (to check once we know all listeners)
yellEavesDrop[client] = clientEyePos
end
end
if (yellEavesDrop) then
-- copy potential eavesdroppers
local clients = yellEavesDrop
yellEavesDrop = {}
-- compile list of valid listener positions
local toCheck = {}
for _, listener in ipairs(listeners) do
-- people not actually on the channel do not count
if (!listenersByKeys[listener]) then continue end
-- admins in observer don't count
if (listener:GetMoveType() == MOVETYPE_NOCLIP and !listener:InVehicle()) then continue end
toCheck[#toCheck + 1] = listener:EyePos()
end
-- compile list of actual eavesdroppers
for client, clientEyePos in pairs(clients) do
for _, listenerPos in ipairs(toCheck) do
if (clientEyePos:DistToSqr(listenerPos) <= range / 8) then
yellEavesDrop[#yellEavesDrop + 1] = client
continue
end
end
end
end
ix.chat.Send(speaker, "radio", text, false, listeners, data)
if (eavesdrop and #eavesdrop > 0) then
ix.chat.Send(speaker, "radio_eavesdrop", text, false, eavesdrop, data)
end
if (yellEavesDrop and #yellEavesDrop > 0) then
ix.chat.Send(speaker, "radio_eavesdrop_yell", text, false, yellEavesDrop, data)
end
end
function ix.radio:AddListenerToChannel(client, channelID)
local channel = self:FindByID(channelID)
if (channel and !channel.listenersByKeys[client] and self:CharacterHasChannel(client:GetCharacter(), channelID)) then
channel.listeners[#channel.listeners + 1] = client
channel.listenersByKeys[client] = #channel.listeners
local clientChannels = client:GetLocalVar("radioChannels", {})
clientChannels[channel.uniqueID] = true
client:SetLocalVar("radioChannels", clientChannels)
if (!self:FindByID(client:GetCharacter():GetRadioChannel())) then
client:GetCharacter():SetRadioChannel(channelID)
end
end
end
function ix.radio:RemoveListenerFromChannel(client, channelID)
local channel = self:FindByID(channelID)
if (channel and channel.listenersByKeys[client] and !self:CharacterHasChannel(client:GetCharacter(), channel.uniqueID)) then
-- Move last listeners into client's slot, overwrite client to remove
local key = channel.listenersByKeys[client]
channel.listeners[key] = channel.listeners[#channel.listeners]
-- Update key of moved client
channel.listenersByKeys[channel.listeners[key]] = key
-- Remove last listeners
channel.listeners[#channel.listeners] = nil
-- Clear client key
channel.listenersByKeys[client] = nil
local clientChannels = client:GetLocalVar("radioChannels", {})
clientChannels[channel.uniqueID] = nil
client:SetLocalVar("radioChannels", clientChannels)
-- Reset transmit channel if client doesn't have this channel anymore
if (client:GetCharacter():GetRadioChannel() == channel.uniqueID) then
local channels = self:GetAllChannelsFromChar(client:GetCharacter())
client:GetCharacter():SetRadioChannel(channels and channels[1] or "")
end
end
end
function ix.radio:AddStationaryToChannel(channelID, entity)
local channel = self:FindByID(channelID)
if (channel and IsValid(entity)) then
table.insert(channel.stationaries, entity)
end
end
function ix.radio:RemoveStationaryFromChannel(channelID, entity)
local channel = self:FindByID(channelID)
if (channel and IsValid(entity)) then
for k, v in ipairs(channel.stationaries) do
if (v == entity) then
table.remove(channel.stationaries, k)
return
end
end
end
end
function ix.radio:CleanStationariesFromChannel(channelID)
local channel = self:FindByID(channelID)
if (channel) then
for i = #channel.stationaries, 1, -1 do
if (!IsValid(channel.stationaries[i])) then
table.remove(channel.stationaries, i)
end
end
end
end
function ix.radio:AddPlayerChannelSubscription(client, channelID)
local channel = self:FindByID(channelID)
if (channel) then
local character = client:GetCharacter()
character:SetRadioChannels(channel.uniqueID)
self:AddListenerToChannel(client, channel.uniqueID)
end
end
function ix.radio:RemovePlayerChannelSubscription(client, channelID)
local channel = self:FindByID(channelID)
if (channel) then
local character = client:GetCharacter()
character:SetRadioChannels(channel.uniqueID, true)
self:RemoveListenerFromChannel(character, channelID)
end
end