This commit is contained in:
lifestorm
2024-08-05 18:40:29 +03:00
parent 9f505a0646
commit c6d9b6f580
8044 changed files with 1853472 additions and 21 deletions

View File

@@ -0,0 +1,561 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PANEL = {}
local function CheckItemRates(actualTD)
if actualTD.highRateProduction < actualTD.averageRateProduction and
actualTD.highRateProduction < actualTD.lowRateProduction and
actualTD.averageRateProduction < actualTD.lowRateProduction then
return true
end
return false
end
function PANEL:CreateDivider(parent, dock)
local divider = parent:Add("Panel")
divider:Dock(dock)
divider:SetHeight(SScaleMin(10 / 3))
divider.Paint = function(s, w, h)
surface.SetDrawColor(111, 111, 136, 76)
surface.DrawLine(0, h * 0.5, w, h * 0.5)
end
end
function PANEL:Init()
if (ix.gui.ctEditor and ix.gui.ctEditor != self) then
ix.gui.ctEditor:Remove()
end
ix.gui.ctEditor = self
self:SetSize(ScrW(), ScrH())
self.typeData = {}
self.typeList = {}
self.innerContent = self:Add("Panel")
self.innerContent:SetSize(SScaleMin(900 / 3), SScaleMin(640 / 3))
self.innerContent:Center()
self.innerContent:MakePopup()
self.innerContent.Paint = function(s, w, h)
surface.SetDrawColor(0, 0, 0, 130)
surface.DrawRect(0, 0, w, h)
end
self.topbar = self.innerContent:Add("Panel")
self.topbar:SetHeight(SScaleMin(40 / 3))
self.topbar:Dock(TOP)
self.topbar.Paint = function(s, width, height)
surface.SetDrawColor(8, 8, 8, 130)
surface.DrawRect(0, 0, width, height)
surface.SetDrawColor(111, 111, 136, 76)
surface.DrawLine(0, height * 0.95, width, height * 0.95)
end
local exit = self.topbar:Add("DImageButton")
exit:SetMaterial(Material("willardnetworks/tabmenu/navicons/exit.png", "smooth"))
exit:SetSize(SScaleMin(25 / 3), SScaleMin(20 / 3))
exit:DockMargin(0, SScaleMin(6 / 3), SScaleMin(6 / 3), SScaleMin(6 / 3))
exit:Dock(RIGHT)
exit.DoClick = function()
self:Remove()
surface.PlaySound("helix/ui/press.wav")
end
local titleText = self.topbar:Add("DLabel")
titleText:SetFont("CharCreationBoldTitleNoClamp")
titleText:Dock(LEFT)
titleText:SetText("City Type Editor")
titleText:DockMargin(SScaleMin(10 / 3), 0, 0, 0)
titleText:SetContentAlignment(4)
titleText:SizeToContents()
end
function PANEL:AddTypeToList(typeID, parent, typeData)
local pnl = parent:Add("DButton")
pnl:Dock(LEFT)
pnl:DockMargin(SScaleMin(6 / 3), SScaleMin(6 / 3), SScaleMin(6 / 3), 0)
pnl:SetFont("TitlesFontNoClamp")
pnl:SetText(typeID)
pnl:SetWide(SScaleMin(128 / 3))
pnl.typeData = typeData
pnl.DoClick = function(s)
self:BuildEditor(s.typeData)
surface.PlaySound("willardnetworks/charactercreation/boop" .. math.random(1, 3) .. ".wav")
end
pnl.DoRightClick = function(s)
local menu = DermaMenu()
menu:AddOption( "Remove", function()
Derma_Query("Are you sure you want to remove this type?", "REMOVING TYPE",
"Yes", function()
net.Start("ix.city.RemoveType")
net.WriteString(s.typeData.name)
net.SendToServer()
self.typeData[s.typeData.name] = nil
if (self.actualTD and self.actualTD.name == s.typeData.name and self.innerScroller) then
self.innerScroller:Remove()
end
s:Remove()
surface.PlaySound("willardnetworks/datapad/close.wav")
end,
"No", nil)
end)
menu:Open()
end
parent:AddPanel( pnl )
self.typeList[#self.typeList + 1] = pnl
return pnl
end
function PANEL:CreateItemButton(itemID, parent, category)
if (self.itemsPanel.items[itemID]) then
return LocalPlayer():NotifyLocalized("Item already exists or its invalid.")
end
self.itemsPanel.items[itemID] = category
if category == "high" then
self.actualTD.itemsHighRate[itemID] = true
elseif category == "average" then
self.actualTD.itemsAverageRate[itemID] = true
elseif category == "low" then
self.actualTD.itemsLowRate[itemID] = true
end
local button = parent:Add("DButton")
button:SetContentAlignment(5)
button:SetFont("LargerTitlesFontNoClamp")
button:SetText(ix.item.list[itemID].name)
button:Dock(TOP)
button:SetHeight(SScaleMin(64 / 3))
button:DockMargin(SScaleMin(6 / 3), SScaleMin(6 / 3), SScaleMin(6 / 3), 0)
button.DoClick = function(s)
local menu = DermaMenu()
menu:AddOption( "Remove", function()
Derma_Query("Are you sure you want to remove this item?", "REMOVING ITEM",
"Yes", function()
self.itemsPanel.items[itemID] = nil
if category == "high" then
self.actualTD.itemsHighRate[itemID] = nil
elseif category == "average" then
self.actualTD.itemsAverageRate[itemID] = nil
elseif category == "low" then
self.actualTD.itemsLowRate[itemID] = nil
end
surface.PlaySound("willardnetworks/datapad/close.wav")
s:Remove()
end,
"No", nil)
end)
menu:Open()
end
local icon = button:Add("SpawnIcon")
icon:SetModel(ix.item.list[itemID].model)
icon:Dock(LEFT)
end
function PANEL:Populate()
if ix.gui.fundManager and IsValid(ix.gui.fundManager) then
ix.gui.fundManager:Remove()
end
self.returnButton = self.innerContent:Add("DButton")
self.returnButton:SetContentAlignment(5)
self.returnButton:SetFont("LargerTitlesFontNoClamp")
self.returnButton:SetText("RETURN")
self.returnButton:Dock(TOP)
self.returnButton:SetHeight(SScaleMin(32 / 3))
self.returnButton:DockMargin(SScaleMin(6 / 3), 0, SScaleMin(6 / 3), 0)
self.returnButton.DoClick = function(s)
self:Remove()
vgui.Create("ixFundManager")
end
self.createType = self.innerContent:Add("DButton")
self.createType:SetContentAlignment(5)
self.createType:SetFont("LargerTitlesFontNoClamp")
self.createType:SetText("CREATE TYPE")
self.createType:Dock(TOP)
self.createType:SetHeight(SScaleMin(32 / 3))
self.createType:DockMargin(SScaleMin(6 / 3), SScaleMin(6 / 3), SScaleMin(6 / 3), 0)
self.createType.DoClick = function(s)
Derma_StringRequest("Type name", "Insert type name here.", "", function(text)
if self.typeData[text] then
return LocalPlayer():NotifyLocalized("Type with this name already exists.")
end
net.Start("ix.city.CreateType")
net.WriteString(text)
net.SendToServer()
net.Start("ix.city.RequestUpdateTypes")
net.SendToServer()
end)
end
self:CreateDivider(self.innerContent, TOP)
self.typePanel = self.innerContent:Add("DHorizontalScroller")
self.typePanel:Dock(TOP)
self.typePanel:DockMargin(SScaleMin(6 / 3), 0, SScaleMin(12 / 3), 0)
self.typePanel:SetHeight(SScaleMin(48 / 3))
self.typePanel:SetOverlap(-64)
for typeID, type in pairs(self.typeData) do
self:AddTypeToList(typeID, self.typePanel, type)
end
self:CreateDivider(self.innerContent, TOP)
end
function PANEL:CreateOptionWang(parent, text, dock, font)
local pnl = parent:Add("Panel")
pnl:Dock(dock)
pnl:DockMargin(SScaleMin(3 / 3), SScaleMin(3 / 3), SScaleMin(3 / 3), SScaleMin(3 / 3))
pnl:SetWide(SScaleMin( (480 / 3) / 3))
local label = pnl:Add("DLabel")
label:SetFont(font or "SubtitleFont")
label:Dock(TOP)
label:SetText(text)
label:SetContentAlignment(5)
label:SizeToContents()
local numWang = pnl:Add("DNumberWang")
numWang:Dock(BOTTOM)
numWang:DockMargin(SScaleMin(48 / 3), 0, SScaleMin(48 / 3), 0)
numWang:SetMax(9999)
numWang.Paint = function(s, w, h)
surface.SetDrawColor(111, 111, 136, 76)
surface.DrawOutlinedRect(0, 0, w, h, 1)
draw.SimpleText(s:GetValue(), "SubtitleFont", w * 0.25, h * 0.15)
end
return numWang
end
local btnColor = Color(111, 111, 136, 255)
function PANEL:UpdateTypes(newTbl)
self.typeData = newTbl
for _, pnl in pairs(self.typeList) do
pnl:Remove()
end
if (self.innerScroller) then
self.innerScroller:Remove()
end
for typeID, type in pairs(self.typeData) do
self:AddTypeToList(typeID, self.typePanel, type)
end
end
function PANEL:BuildEditor(typeData)
if (self.innerScroller) then
self.innerScroller:Remove()
end
self.actualTD = typeData
self.innerScroller = self.innerContent:Add("DScrollPanel")
self.innerScroller:Dock(FILL)
local itemsText = self.innerScroller:Add("DLabel")
itemsText:SetFont("CharCreationBoldTitleNoClamp")
itemsText:Dock(TOP)
itemsText:SetText("ITEM PRODUCTION TABLES")
itemsText:DockMargin(0, SScaleMin(12 / 3), 0, 0)
itemsText:SetContentAlignment(5)
itemsText:SizeToContents()
self.itemsPanel = self.innerScroller:Add("Panel")
self.itemsPanel:Dock(TOP)
self.itemsPanel:SetHeight(SScaleMin(348 / 3))
self.itemsPanel:DockMargin(SScaleMin(8 / 3), SScaleMin(4 / 3), 0, 0)
self.itemsPanel.items = {}
self.itemsHPScroller = self.itemsPanel:Add("DScrollPanel")
self.itemsHPScroller:Dock(LEFT)
self.itemsHPScroller:DockMargin(SScaleMin(12 / 3), 0, 0, 0)
self.itemsHPScroller:SetWide(self.innerContent:GetWide() * 0.31)
self.itemsHPScroller.Paint = function(s, w, h)
surface.SetDrawColor(111, 111, 136, 76)
surface.DrawOutlinedRect(0, 0, w, h, 2)
end
local hpText = self.itemsHPScroller:Add("DLabel")
hpText:SetFont("TitlesFontNoBoldNoClamp")
hpText:Dock(TOP)
hpText:SetText("HIGH PRODUCTION")
hpText:DockMargin(0, SScaleMin(4 / 3), 0, 0)
hpText:SetContentAlignment(5)
hpText:SizeToContents()
local addHPButton = self.itemsHPScroller:Add("DButton")
addHPButton:SetFont("MenuFontNoClamp")
addHPButton:Dock(TOP)
addHPButton:SetText("Add item")
addHPButton:DockMargin(SScaleMin(36 / 3), SScaleMin(6 / 3), SScaleMin(36 / 3), 0)
addHPButton:SetContentAlignment(5)
addHPButton:SizeToContents()
addHPButton.Paint = function(s, w, h)
surface.SetDrawColor(Color(0, 0, 0, 100))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(btnColor)
surface.DrawOutlinedRect(0, 0, w, h)
end
addHPButton.DoClick = function(s)
surface.PlaySound("helix/ui/press.wav")
Derma_StringRequest("Item ID", "Insert item's ID you want to add here.", "", function(text)
if !ix.item.list[text] then
return LocalPlayer():NotifyLocalized("Wrong item ID.")
end
self:CreateItemButton(text, self.itemsHPScroller, "high")
end)
end
self:CreateDivider(self.itemsHPScroller, TOP)
self.itemsAPScroller = self.itemsPanel:Add("DScrollPanel")
self.itemsAPScroller:Dock(LEFT)
self.itemsAPScroller:DockMargin(SScaleMin(12 / 3), 0, 0, 0)
self.itemsAPScroller:SetWide(self.innerContent:GetWide() * 0.31)
self.itemsAPScroller.Paint = function(s, w, h)
surface.SetDrawColor(111, 111, 136, 76)
surface.DrawOutlinedRect(0, 0, w, h, 2)
end
local apText = self.itemsAPScroller:Add("DLabel")
apText:SetFont("TitlesFontNoBoldNoClamp")
apText:Dock(TOP)
apText:SetText("AVERAGE PRODUCTION")
apText:DockMargin(0, SScaleMin(4 / 3), 0, 0)
apText:SetContentAlignment(5)
apText:SizeToContents()
local addAPButton = self.itemsAPScroller:Add("DButton")
addAPButton:SetFont("MenuFontNoClamp")
addAPButton:Dock(TOP)
addAPButton:SetText("Add item")
addAPButton:DockMargin(SScaleMin(36 / 3), SScaleMin(6 / 3), SScaleMin(36 / 3), 0)
addAPButton:SetContentAlignment(5)
addAPButton:SizeToContents()
addAPButton.Paint = function(s, w, h)
surface.SetDrawColor(Color(0, 0, 0, 100))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(btnColor)
surface.DrawOutlinedRect(0, 0, w, h)
end
addAPButton.DoClick = function(s)
surface.PlaySound("helix/ui/press.wav")
Derma_StringRequest("Item ID", "Insert item's ID you want to add here.", "", function(text)
if !ix.item.list[text] then
return LocalPlayer():NotifyLocalized("Wrong item ID.")
end
self:CreateItemButton(text, self.itemsAPScroller, "average")
end)
end
self:CreateDivider(self.itemsAPScroller, TOP)
self.itemsLPScroller = self.itemsPanel:Add("DScrollPanel")
self.itemsLPScroller:Dock(LEFT)
self.itemsLPScroller:DockMargin(SScaleMin(12 / 3), 0, 0, 0)
self.itemsLPScroller:SetWide(self.innerContent:GetWide() * 0.31)
self.itemsLPScroller.Paint = function(s, w, h)
surface.SetDrawColor(111, 111, 136, 76)
surface.DrawOutlinedRect(0, 0, w, h, 2)
end
local lpText = self.itemsLPScroller:Add("DLabel")
lpText:SetFont("TitlesFontNoBoldNoClamp")
lpText:Dock(TOP)
lpText:SetText("LOW PRODUCTION")
lpText:DockMargin(0, SScaleMin(4 / 3), 0, 0)
lpText:SetContentAlignment(5)
lpText:SizeToContents()
local addLPButton = self.itemsLPScroller:Add("DButton")
addLPButton:SetFont("MenuFontNoClamp")
addLPButton:Dock(TOP)
addLPButton:SetText("Add item")
addLPButton:DockMargin(SScaleMin(36 / 3), SScaleMin(6 / 3), SScaleMin(36 / 3), 0)
addLPButton:SetContentAlignment(5)
addLPButton:SizeToContents()
addLPButton.Paint = function(s, w, h)
surface.SetDrawColor(Color(0, 0, 0, 100))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(btnColor)
surface.DrawOutlinedRect(0, 0, w, h)
end
addLPButton.DoClick = function(s)
surface.PlaySound("helix/ui/press.wav")
Derma_StringRequest("Item ID", "Insert item's ID you want to add here.", "", function(text)
if !ix.item.list[text] then
return LocalPlayer():NotifyLocalized("Wrong item ID.")
end
self:CreateItemButton(text, self.itemsLPScroller, "low")
end)
end
self:CreateDivider(self.itemsLPScroller, TOP)
for itemID, _ in pairs(self.actualTD.itemsHighRate) do
self:CreateItemButton(itemID, self.itemsHPScroller, "high")
end
for itemID, _ in pairs(self.actualTD.itemsAverageRate) do
self:CreateItemButton(itemID, self.itemsAPScroller, "average")
end
for itemID, _ in pairs(self.actualTD.itemsLowRate) do
self:CreateItemButton(itemID, self.itemsLPScroller, "low")
end
local productionPanel = self.innerScroller:Add("Panel")
productionPanel:Dock(TOP)
productionPanel:SetHeight(SScaleMin(96 / 3))
productionPanel:DockMargin(SScaleMin(196 / 3), SScaleMin(4 / 3), SScaleMin(196 / 3), 0)
local high = self:CreateOptionWang(productionPanel, "HIGH PRODUCTION RATE", LEFT)
high:SetValue(self.actualTD.highRateProduction)
high:GetParent():SetHelixTooltip(function(tooltip)
local name = tooltip:AddRow("name")
name:SetImportant()
name:SetText("High production rate")
name:SizeToContents()
local info = tooltip:AddRow("info")
info:SetText("Defines the rate of production in hours. If you'll leave this row with value of 1, the items from high production category will produce every hour.")
info:SizeToContents()
tooltip:SizeToContents()
end)
high.OnValueChanged = function(s, value)
self.actualTD.highRateProduction = value
end
local avrg = self:CreateOptionWang(productionPanel, "AVERAGE PRODUCTION RATE", LEFT)
avrg:SetValue(self.actualTD.averageRateProduction)
avrg:GetParent():SetHelixTooltip(function(tooltip)
local name = tooltip:AddRow("name")
name:SetImportant()
name:SetText("Average production rate")
name:SizeToContents()
local info = tooltip:AddRow("info")
info:SetText("Defines the rate of production in hours. If you'll leave this row with value of 1, the items from high production category will produce every hour.")
info:SizeToContents()
tooltip:SizeToContents()
end)
avrg.OnValueChanged = function(s, value)
self.actualTD.averageRateProduction = value
end
local low = self:CreateOptionWang(productionPanel, "LOW PRODUCTION RATE", LEFT)
low:SetValue(self.actualTD.lowRateProduction)
low:GetParent():SetHelixTooltip(function(tooltip)
local name = tooltip:AddRow("name")
name:SetImportant()
name:SetText("Low production rate")
name:SizeToContents()
local info = tooltip:AddRow("info")
info:SetText("Defines the rate of production in hours. If you'll leave this row with value of 1, the items from high production category will produce every hour.")
info:SizeToContents()
tooltip:SizeToContents()
end)
low.OnValueChanged = function(s, value)
self.actualTD.lowRateProduction = value
end
self:CreateDivider(self.innerScroller, TOP)
local incomeText = self.innerScroller:Add("DLabel")
incomeText:SetFont("CharCreationBoldTitleNoClamp")
incomeText:Dock(TOP)
incomeText:SetText("CREDIT INCOME")
incomeText:DockMargin(0, SScaleMin(12 / 3), 0, 0)
incomeText:SetContentAlignment(5)
incomeText:SizeToContents()
local incomePanel = self.innerScroller:Add("Panel")
incomePanel:Dock(TOP)
incomePanel:SetHeight(SScaleMin(96 / 3))
local passiveIncome = incomePanel:Add("Panel")
passiveIncome:Dock(LEFT)
passiveIncome:SetWide(SScaleMin(225 / 3))
passiveIncome:DockMargin(SScaleMin(64 / 3), 1, 0, 0)
local incomeWang = self:CreateOptionWang(passiveIncome, "Passive income in credits", FILL, "TitlesFontNoBoldNoClamp")
incomeWang:SetValue(self.actualTD.passiveIncome)
incomeWang.OnValueChanged = function(s, value)
self.actualTD.passiveIncome = value
end
local passiveIncomeRate = incomePanel:Add("Panel")
passiveIncomeRate:SetWide(SScaleMin(225 / 3))
passiveIncomeRate:DockMargin(0, 1, SScaleMin(64 / 3), 0)
passiveIncomeRate:Dock(RIGHT)
local rateWang = self:CreateOptionWang(passiveIncomeRate, "Passive income in hours", FILL, "TitlesFontNoBoldNoClamp")
rateWang:SetValue(self.actualTD.passiveIncomeRate)
rateWang.OnValueChanged = function(s, value)
self.actualTD.passiveIncomeRate = value
end
self:CreateDivider(self.innerScroller, TOP)
local saveChanges = self.innerScroller:Add("DButton")
saveChanges:SetFont("MenuFontNoClamp")
saveChanges:Dock(TOP)
saveChanges:SetText("SAVE CHANGES")
saveChanges:DockMargin(SScaleMin(96 / 3), SScaleMin(6 / 3), SScaleMin(96 / 3), SScaleMin(6 / 3))
saveChanges:SetContentAlignment(5)
saveChanges:SizeToContents()
saveChanges.Paint = function(s, w, h)
surface.SetDrawColor(Color(0, 0, 0, 100))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(btnColor)
surface.DrawOutlinedRect(0, 0, w, h)
end
saveChanges.DoClick = function(s)
if !CheckItemRates(self.actualTD) then
return LocalPlayer():NotifyLocalized("You've settuped item production variables in a wrong way. High rate must be not more than average, and low rate must be the biggest value.")
end
Derma_Query("Are you sure you want to save the changes you've made?", "SAVING CHANGES",
"Yes", function()
net.Start("ix.city.UpdateType")
net.WriteString(util.TableToJSON(self.actualTD))
net.SendToServer()
end,
"No", nil)
end
self:CreateDivider(self.innerScroller, TOP)
end
function PANEL:Paint(w, h)
surface.SetDrawColor(63, 58, 115, 220)
surface.DrawRect(0, 0, w, h)
Derma_DrawBackgroundBlur(self, 1)
end
vgui.Register("ixCtEditor", PANEL, "Panel")

View File

@@ -0,0 +1,546 @@
--[[
| 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:AddCityToList(cityID, parent, cityData)
local pnl = parent:Add("DButton")
pnl:Dock(TOP)
pnl:DockMargin(SScaleMin(6 / 3), SScaleMin(6 / 3), SScaleMin(6 / 3), 0)
pnl:SetFont("TitlesFontNoClamp")
pnl:SetText(cityID != "1" and "CITY-" .. cityID or "CITY-" .. ix.config.Get("mainCityNumber", 24))
pnl:SetHeight(SScaleMin(32 / 3))
pnl.cityData = cityData
pnl.DoClick = function(s)
self:BuildEditor(cityID == "1", s.cityData)
surface.PlaySound("willardnetworks/charactercreation/boop" .. math.random(1, 3) .. ".wav")
end
pnl.DoRightClick = function(s)
if s.cityData.id == "1" then
return
end
local menu = DermaMenu()
menu:AddOption( "Remove", function()
Derma_Query("Are you sure you want to remove this city?", "REMOVING CITY",
"Yes", function()
net.Start("ix.city.RemoveCity")
net.WriteString(s.cityData.id)
net.SendToServer()
self.cities[s.cityData.id] = nil
if (self.cityData.id == s.cityData.id and self.editorPanel) then
self.cityData.id:Remove()
end
s:Remove()
surface.PlaySound("willardnetworks/datapad/close.wav")
end,
"No", nil)
end)
menu:Open()
end
self.cityList[#self.cityList + 1] = pnl
return pnl
end
function PANEL:CreateButton(parent, text, color, callback)
parent:Dock(TOP)
parent:SetText(text)
parent:SetHeight(SScaleMin(36 / 3))
parent:DockMargin(SScaleMin(8 / 3), SScaleMin(6 / 3), 0, 0)
parent:SetFont("MenuFontNoClamp")
parent.Paint = function(s, w, h)
surface.SetDrawColor(Color(0, 0, 0, 100))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(color)
surface.DrawOutlinedRect(0, 0, w, h)
end
parent.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
callback()
end
end
function PANEL:RequestPopulate()
net.Start("ix.city.PopulateFunds")
net.SendToServer()
end
function PANEL:Populate(data)
self.cities = data
for index, city in pairs(self.cities) do
self:AddCityToList(city.id, self.cityListFrame, city)
end
end
function PANEL:CreateLabeledNumWang(parent, text, dock, icon)
local pnl = parent:Add("Panel")
pnl:Dock(dock)
pnl:DockMargin(SScaleMin(6 / 3), SScaleMin(6 / 3), SScaleMin(6 / 3), SScaleMin(6 / 3))
pnl:SetWide(parent:GetWide() * 0.84)
local label = pnl:Add("DLabel")
label:SetFont("SubtitleFont")
label:Dock(TOP)
label:SetText(text)
label:SetContentAlignment(5)
label:SizeToContents()
local iconP = pnl:Add("Panel")
iconP:Dock(TOP)
iconP:SetHeight(SScaleMin(16 / 3))
iconP:DockMargin(0, SScaleMin(6 / 3), 0, 0)
iconP.Paint = function(s, w, h)
surface.SetDrawColor(255, 255, 255)
surface.SetMaterial(icon)
surface.DrawTexturedRect(w * .35, 0, 16, 16)
end
local numWang = pnl:Add("DNumberWang")
numWang:Dock(BOTTOM)
numWang:SetMax(9999)
numWang.Paint = function(s, w, h)
surface.SetDrawColor(111, 111, 136, 76)
surface.DrawOutlinedRect(0, 0, w, h, 1)
draw.SimpleText(s:GetValue(), "SubtitleFont", w * 0.25, h * 0.15)
end
return numWang
end
local priceMat = Material("willardnetworks/tabmenu/charmenu/chips.png", "smooth")
local amountMat = Material("willardnetworks/tabmenu/navicons/inventory.png", "smooth")
local mulTDMat = Material("willardnetworks/tabmenu/crafting/plus.png", "smooth")
local redTDMat = Material("willardnetworks/tabmenu/crafting/minus.png", "smooth")
function PANEL:CreateItemButton(itemID, parent, data, isMain)
if (!self.cityData.items[itemID] or parent.items[itemID]) then
return LocalPlayer():NotifyLocalized("Item already exists or its invalid.")
end
parent.items[itemID] = true
local button = parent:Add("DButton")
button:SetContentAlignment(5)
button:SetFont("LargerTitlesFontNoClamp")
button:SetText(ix.item.list[itemID].name)
button:Dock(TOP)
button:SetHeight(SScaleMin(64 / 3))
button:DockMargin(SScaleMin(6 / 3), SScaleMin(6 / 3), SScaleMin(6 / 3), 0)
local icon = button:Add("SpawnIcon")
icon:SetModel(ix.item.list[itemID].model)
icon:Dock(LEFT)
local adjustment = parent:Add("Panel")
adjustment:Dock(TOP)
adjustment:DockMargin(SScaleMin(6 / 3), 0, SScaleMin(6 / 3), 0)
adjustment:SetHeight(SScaleMin(112 / 3))
adjustment.Paint = function(s, w, h)
surface.SetDrawColor(8, 8, 8, 130)
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(111, 111, 136, 76)
surface.DrawOutlinedRect(0, 0, w, h, 1)
end
local amount = self:CreateLabeledNumWang(adjustment, "Amount", LEFT, amountMat)
amount:GetParent():SetHelixTooltip(function(tooltip)
local name = tooltip:AddRow("name")
name:SetImportant()
name:SetText("Amount")
name:SizeToContents()
local info = tooltip:AddRow("info")
info:SetText("Current accessable amount of this item.")
info:SizeToContents()
tooltip:SizeToContents()
end)
amount.OnValueChanged = function(s, value)
self.cityData.items[itemID].amount = value
end
amount:SetValue(data and data.amount or 0)
self.cityData.items[itemID].amount = amount:GetValue()
if (!isMain) then
local price = self:CreateLabeledNumWang(adjustment, "Price", LEFT, priceMat)
price:GetParent():SetHelixTooltip(function(tooltip)
local name = tooltip:AddRow("name")
name:SetImportant()
name:SetText("Price")
name:SizeToContents()
local info = tooltip:AddRow("info")
info:SetText("This is default price of an item not affected by abundance and lack thresholds.")
info:SizeToContents()
tooltip:SizeToContents()
end)
price.OnValueChanged = function(s, value)
self.cityData.items[itemID].price = value
end
price:SetValue(data and data.price or 0)
self.cityData.items[itemID].price = price:GetValue()
local mulTD = self:CreateLabeledNumWang(adjustment, "Mul.TD", LEFT, mulTDMat)
mulTD:GetParent():SetHelixTooltip(function(tooltip)
local name = tooltip:AddRow("name")
name:SetImportant()
name:SetText("Lack threshold")
name:SizeToContents()
local info = tooltip:AddRow("info")
info:SetText("How many of this items must be in stock to consider them 'lacking'. If item amount is lower than this value - then its price multiplicates by P.Mul value.")
info:SizeToContents()
tooltip:SizeToContents()
end)
mulTD:SetValue(data and data.priceMulptiplicationTD or 10)
self.cityData.items[itemID].priceMulptiplicationTD = mulTD:GetValue()
mulTD.OnValueChanged = function(s, value)
self.cityData.items[itemID].priceMulptiplicationTD = value
end
local redTD = self:CreateLabeledNumWang(adjustment, "Red.TD", LEFT, redTDMat)
redTD:GetParent():SetHelixTooltip(function(tooltip)
local name = tooltip:AddRow("name")
name:SetImportant()
name:SetText("Abundance threshold")
name:SizeToContents()
local info = tooltip:AddRow("info")
info:SetText("How many of this items must be in stock to consider them 'abundant'. If item amount is more than this value - then its price divides by P.Div value.")
info:SizeToContents()
tooltip:SizeToContents()
end)
redTD:SetValue(data and data.priceReductionTD or 90)
self.cityData.items[itemID].priceReductionTD = redTD:GetValue()
redTD.OnValueChanged = function(s, value)
self.cityData.items[itemID].priceReductionTD = value
end
local pMul = self:CreateLabeledNumWang(adjustment, "P.Mul", LEFT, mulTDMat)
pMul:SetValue(data and data.priceMul or 2)
self.cityData.items[itemID].priceMul = pMul:GetValue()
pMul.OnValueChanged = function(s, value)
self.cityData.items[itemID].priceMul = value
end
local pDiv = self:CreateLabeledNumWang(adjustment, "P.Div", LEFT, redTDMat)
pDiv:SetValue(data and data.priceDiv or 2)
self.cityData.items[itemID].priceDiv = pDiv:GetValue()
pDiv.OnValueChanged = function(s, value)
self.cityData.items[itemID].priceDiv = value
end
end
end
function PANEL:CreateDivider(parent, dock)
local divider = parent:Add("Panel")
divider:Dock(dock)
divider:SetHeight(SScaleMin(10 / 3))
divider.Paint = function(s, w, h)
surface.SetDrawColor(111, 111, 136, 76)
surface.DrawLine(0, h * 0.5, w, h * 0.5)
end
end
function PANEL:AddItemToCityData(itemID)
self.cityData.items[itemID] = {}
end
function PANEL:BuildEditor(isMain, cityData)
if IsValid(self.editorPanel) then
self.editorPanel:Remove()
end
self.cityData = {}
self.cityData = cityData
self.editorPanel = self.cityPanel:Add("DScrollPanel")
self.editorPanel:Dock(FILL)
local cityID = cityData.id
local cityName = self.editorPanel:Add("DLabel")
cityName:SetFont("TitlesFontNoBoldNoClamp")
cityName:Dock(TOP)
cityName:SetText(cityID != "1" and "CITY-" .. cityID or "CITY-" .. ix.config.Get("mainCityNumber", 24))
cityName:SetContentAlignment(5)
cityName:SizeToContents()
self:CreateDivider(self.editorPanel, TOP)
if (!isMain) then
local type = self.editorPanel:Add("DLabel")
type:SetFont("TitlesFontNoBoldNoClamp")
type:Dock(TOP)
type:SetText("TYPE")
type:SetContentAlignment(5)
type:SizeToContents()
local curType = self.editorPanel:Add("DLabel")
curType:SetFont("MenuFontOutlined")
curType:SetText(cityData.type.name and "CURRENT TYPE: " .. cityData.type.name or "THIS CITY DON'T HAVE ANY TYPE YET")
curType:Dock(TOP)
curType:SizeToContents()
local typeButton = self.editorPanel:Add("DButton")
self:CreateButton(typeButton, "CHANGE TYPE", Color(111, 111, 136, 255), function()
local types = DermaMenu()
for index, t in pairs(self.types) do
types:AddOption(index, function()
cityData.type = self.types[index]
curType:SetText(cityData.type and "CURRENT TYPE: " .. cityData.type.name)
curType:SizeToContents()
end)
end
types:Open()
end)
typeButton:DockMargin(0, SScaleMin(16 / 3), 0, SScaleMin(16 / 3))
typeButton:SetHeight(SScaleMin(29 / 3))
self:CreateDivider(self.editorPanel, TOP)
local items = self.editorPanel:Add("DLabel")
items:SetFont("TitlesFontNoBoldNoClamp")
items:Dock(TOP)
items:SetText("ITEMS")
items:SetContentAlignment(5)
items:SizeToContents()
end
self.itemsPanel = self.editorPanel:Add("DScrollPanel")
self.itemsPanel:Dock(TOP)
self.itemsPanel:SetHeight(SScaleMin(400 / 3))
self.itemsPanel.Paint = function(s, w, h)
surface.SetDrawColor(111, 111, 136, 76)
surface.DrawOutlinedRect(0, 0, w, h, 2)
end
self.itemsPanel.items = {}
for item, itemTbl in pairs(self.cityData.items) do
self:CreateItemButton(item, self.itemsPanel, itemTbl, isMain)
end
local createItemButton = self.editorPanel:Add("DButton")
self:CreateButton(createItemButton, "ADD ITEM", Color(111, 111, 136, 255), function()
Derma_StringRequest("Item ID", "Insert item's ID you want to add here.", "", function(text)
if !ix.item.list[text] then
return LocalPlayer():NotifyLocalized("Wrong item ID.")
end
self:AddItemToCityData(text)
self:CreateItemButton(text, self.itemsPanel, nil, isMain)
end)
end)
createItemButton:DockMargin(0, SScaleMin(16 / 3), 0, SScaleMin(16 / 3))
createItemButton:SetHeight(SScaleMin(29 / 3))
self:CreateDivider(self.editorPanel, TOP)
local credits = self.editorPanel:Add("DLabel")
credits:SetFont("TitlesFontNoBoldNoClamp")
credits:Dock(TOP)
credits:SetText("CREDITS")
credits:SetContentAlignment(5)
credits:SizeToContents()
local credPanel = self.editorPanel:Add("Panel")
credPanel:Dock(TOP)
credPanel:SetHeight(SScaleMin(24 / 3))
credPanel:DockMargin(0, SScaleMin(8 / 3), 0, 0)
local credLabel = credPanel:Add("DLabel")
credLabel:SetFont("TitlesFontNoBoldNoClamp")
credLabel:Dock(LEFT)
credLabel:SetText("CITY CREDITS:")
credLabel:SetContentAlignment(4)
credLabel:SizeToContents()
local credWang = credPanel:Add("DNumberWang")
credWang:Dock(LEFT)
credWang:SetMax(999999)
credWang:DockMargin(SScaleMin(8 / 3), 0, 0, 0)
credWang.Paint = function(s, w, h)
surface.SetDrawColor(111, 111, 136, 76)
surface.DrawOutlinedRect(0, 0, w, h, 1)
draw.SimpleText(s:GetValue(), "SubtitleFont", w * 0.25, h * 0.15)
end
credWang.OnValueChanged = function(s, value)
self.cityData.credits = value
end
credWang:SetValue(self.cityData.credits or 0)
self:CreateDivider(self.editorPanel, TOP)
local saveChangesButton = self.editorPanel:Add("DButton")
self:CreateButton(saveChangesButton, "SAVE CHANGES", Color(111, 111, 136, 255), function()
Derma_Query("Are you sure you want to save the changes you've made?", "SAVING CHANGES",
"Yes", function()
net.Start("ix.city.UpdateCity")
net.WriteString(util.TableToJSON(self.cityData))
net.WriteBool(isMain)
net.SendToServer()
end,
"No", nil)
end)
saveChangesButton:DockMargin(0, SScaleMin(16 / 3), 0, SScaleMin(16 / 3))
saveChangesButton:SetHeight(SScaleMin(29 / 3))
end
function PANEL:Init()
if (ix.gui.fundManager and ix.gui.fundManager != self) then
ix.gui.fundManager:Remove()
end
if (ix.gui.ctEditor and IsValid(ix.gui.ctEditor)) then
ix.gui.ctEditor:Remove()
end
ix.gui.fundManager = self
self:SetSize(ScrW(), ScrH())
self:SetAlpha(0)
self:AlphaTo(255, 0.5, 0)
self.cityList = {}
self.cityData = {}
self.innerContent = self:Add("Panel")
self.innerContent:SetSize(SScaleMin(900 / 3), SScaleMin(640 / 3))
self.innerContent:Center()
self.innerContent:MakePopup()
self.innerContent.Paint = function(s, w, h)
surface.SetDrawColor(0, 0, 0, 130)
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(111, 111, 136, 76)
surface.DrawLine(w * 0.5, SScaleMin(40 / 3), w * 0.5, h)
end
self.topbar = self.innerContent:Add("Panel")
self.topbar:SetHeight(SScaleMin(40 / 3))
self.topbar:Dock(TOP)
self.topbar.Paint = function(s, width, height)
surface.SetDrawColor(8, 8, 8, 130)
surface.DrawRect(0, 0, width, height)
surface.SetDrawColor(111, 111, 136, 76)
surface.DrawLine(0, height * 0.95, width, height * 0.95)
end
local exit = self.topbar:Add("DImageButton")
exit:SetMaterial(Material("willardnetworks/tabmenu/navicons/exit.png", "smooth"))
exit:SetSize(SScaleMin(25 / 3), SScaleMin(20 / 3))
exit:DockMargin(0, SScaleMin(6 / 3), SScaleMin(6 / 3), SScaleMin(6 / 3))
exit:Dock(RIGHT)
exit.DoClick = function()
self:Remove()
surface.PlaySound("helix/ui/press.wav")
end
local titleText = self.topbar:Add("DLabel")
titleText:SetFont("CharCreationBoldTitleNoClamp")
titleText:Dock(LEFT)
titleText:SetText("City Fund Manager")
titleText:DockMargin(SScaleMin(10 / 3), 0, 0, 0)
titleText:SetContentAlignment(4)
titleText:SizeToContents()
self.cityListPanel = self.innerContent:Add("Panel")
self.cityListPanel:Dock(LEFT)
self.cityListPanel:DockMargin(SScaleMin(12 / 3), SScaleMin(6 / 3), 0, SScaleMin(6 / 3))
self.cityListPanel:SetWide(SScaleMin(400 / 3))
self.cityPanel = self.innerContent:Add("Panel")
self.cityPanel:Dock(FILL)
self.cityPanel:DockMargin(SScaleMin(48 / 3), SScaleMin(16 / 3), SScaleMin(16 / 3), SScaleMin(16 / 3))
self.citiesLabel = self.cityListPanel:Add("DLabel")
self.citiesLabel:SetFont("TitlesFontNoBoldNoClamp")
self.citiesLabel:Dock(TOP)
self.citiesLabel:SetText("CITIES")
self.citiesLabel:DockMargin(SScaleMin(8 / 3), SScaleMin(16 / 3), 0, 0)
self.citiesLabel:SetContentAlignment(5)
self.citiesLabel:SizeToContents()
self.cityListFrame = self.cityListPanel:Add("DScrollPanel")
self.cityListFrame:Dock(TOP)
self.cityListFrame:DockMargin(SScaleMin(8 / 3), 1, 0, 0)
self.cityListFrame:SetHeight(SScaleMin(400 / 3))
self.cityListFrame.Paint = function(s, w, h)
surface.SetDrawColor(111, 111, 136, 76)
surface.DrawOutlinedRect(0, 0, w, h, 2)
end
self.cityCreate = self.cityListPanel:Add("DButton")
self:CreateButton(self.cityCreate, "Create city", Color(111, 111, 136, 255), function()
local cityNumber
local cityType
Derma_StringRequest("City number", "Insert city number here.", "", function(text)
text = tonumber(text)
if self.cities[text] or !text then
return LocalPlayer():NotifyLocalized("City with this number already exists or you've entered words instead of number.")
end
cityNumber = tostring(text)
Derma_StringRequest("City type", "Insert city type ID here. It must be accurate.", "", function(typeID)
if !self.types[typeID] then
return LocalPlayer():NotifyLocalized("Type doesn't exist.")
end
cityType = typeID
net.Start("ix.city.CreateCity")
net.WriteString(cityNumber)
net.WriteString(cityType)
net.SendToServer()
net.Start("ix.city.RequestUpdateCities")
net.SendToServer()
end)
end)
end)
self.switchToType = self.cityListPanel:Add("DButton")
self:CreateButton(self.switchToType, "Switch to type editor", Color(111, 111, 136, 255), function()
local ctEditor = vgui.Create("ixCtEditor")
ctEditor.typeData = self.types
ctEditor:Populate()
self:Remove()
end)
self:RequestPopulate()
end
function PANEL:UpdateCities(newTbl)
self.cities = newTbl
for _, pnl in pairs(self.cityList) do
pnl:Remove()
end
if IsValid(self.editorPanel) then
self.editorPanel:Remove()
end
for index, city in pairs(self.cities) do
self:AddCityToList(city.id, self.cityListFrame, city)
end
end
function PANEL:Paint(w, h)
surface.SetDrawColor(63, 58, 115, 220)
surface.DrawRect(0, 0, w, h)
Derma_DrawBackgroundBlur(self, 1)
end
vgui.Register("ixFundManager", PANEL, "Panel")

View File

@@ -0,0 +1,84 @@
--[[
| 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 pairs = pairs
local string = string
local isnumber = isnumber
local util = util
local net = net
ix.city = ix.city or {}
ix.city.list = ix.city.list or {}
ix.city.main = ix.city.main or false
ix.city.types = ix.city.types or {}
ix.city.types.list = ix.city.types.list or {}
ix.city.cwuAccess = {
["Member"] = {
creditInteraction = false,
budgetInteraction = false,
marketInteraction = false,
stockInteraction = true
},
["Management"] = {
creditInteraction = false,
budgetInteraction = true,
marketInteraction = true,
stockInteraction = true
},
["Logistics"] = {
creditInteraction = false,
budgetInteraction = false,
marketInteraction = true,
stockInteraction = true
}
}
function ix.city:TranslateCardLevel(cwuCard)
local accessLevel = cwuCard:GetData("accessLevel", "Member Access")
for reqAcLevel, perms in pairs(ix.city.cwuAccess) do
local s1, s2 = string.find(accessLevel, reqAcLevel)
if !isnumber(s1) or !isnumber(s2) then continue end
local level = string.sub( reqAcLevel, s1, s2 )
return level
end
end
function ix.city:IsAccessable(cwuCard, interaction)
if !cwuCard then return false end
local accessLevel = ix.city:TranslateCardLevel(cwuCard)
if ix.city.cwuAccess[accessLevel] and ix.city.cwuAccess[accessLevel][interaction] then
return true
end
return false
end
if SERVER then
function ix.city:SyncCityStock(client)
local cityStock = util.TableToJSON(ix.city.main.items)
net.Start("ix.city.SyncCityStock")
net.WriteString(cityStock)
net.Send(client)
end
else
function ix.city:SyncCityStock()
net.Start("ix.city.SyncCityStock")
net.SendToServer()
end
end

View File

@@ -0,0 +1,39 @@
--[[
| 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.factionBudget = ix.factionBudget or {}
ix.factionBudget.list = ix.factionBudget.list or {}
function ix.factionBudget:RegisterFB(id, factionName)
if !isstring(id) then return end
id = string.utf8upper(id)
ix.factionBudget.list[id] = {
id = id,
name = factionName,
credits = 0
}
end
function ix.factionBudget:GetFB(id)
return ix.factionBudget.list[id]
end
-- never use "INF" in any case. it breaks every faction with any ID that is "INF".
function ix.factionBudget:InitializeFactionBudgets()
ix.factionBudget:RegisterFB("CWRU", "Research Union")
ix.factionBudget:RegisterFB("CWU", "Civil Workers Union")
ix.factionBudget:RegisterFB("CPU", "Civil Protection")
ix.factionBudget:RegisterFB("CCA", "Civil Administration")
ix.factionBudget:RegisterFB("CMU", "Medical Union")
ix.factionBudget:RegisterFB("BOE", "Enlightenment")
ix.factionBudget:RegisterFB("SCO", "Security Council")
end

View File

@@ -0,0 +1,357 @@
--[[
| 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 isstring = isstring
local setmetatable = setmetatable
local isnumber = isnumber
local tostring = tostring
local util = util
local table = table
local pairs = pairs
local ents = ents
local net = net
local istable = istable
local tonumber = tonumber
ix.city.disallowments = ix.city.disallowments or {}
ix.city.combineRestrictions = ix.city.combineRestrictions or {}
function ix.city:UpdateCityFunds()
for index, city in pairs(ix.city.list) do
if city:IsMain() then
city:IncrementLoanProgress()
end
if !city.type then continue end
city:HandleItemConsumption()
city:IncrementProductionProgress()
city:IncrementIncomeProgress()
end
end
function ix.city:AddDisallowment(itemID)
if !isstring(itemID) then return end
ix.city.disallowments[itemID] = true
end
function ix.city:IsDisallowment(itemID)
return ix.city.disallowments[itemID] or false
end
function ix.city:AddCombineRestriction(itemID)
if !isstring(itemID) then return end
ix.city.combineRestrictions[itemID] = true
end
function ix.city:IsCombineRestricted(itemID)
return ix.city.combineRestrictions[itemID] or false
end
function ix.city:InitializeMainCity()
local city = setmetatable({
id = "1",
credits = 0,
type = {},
items = {},
loan = 0,
loanRate = 0
}, ix.meta.city)
ix.city.main = city
ix.city:AddCityData("1", city)
return city
end
function ix.city:CreateCity(id, type)
if isnumber(id) then id = tostring(id) end
if !ix.city.types.list[type] then return end
if ix.city.list[id] or ix.city.main:GetID() == id then return end
type = ix.city.types.list[type]
local city = setmetatable({
id = id,
credits = 0,
type = type or {},
items = {},
loan = 0,
loanRate = 0
}, ix.meta.city)
city:OnCreated()
ix.city.list[id] = city
ix.city:AddCityData(id, city)
return city
end
function ix.city:LoadType(name, data)
ix.city.types.list[name] = {
name = name,
itemsHighRate = data.itemsHighRate,
itemsLowRate = data.itemsLowRate,
itemsAverageRate = data.itemsAverageRate,
highRateProduction = data.highRateProduction,
lowRateProduction = data.lowRateProduction,
averageRateProduction = data.averageRateProduction,
passiveIncome = data.passiveIncome,
passiveIncomeRate = data.passiveIncomeRate
}
return ix.city.types.list[name]
end
function ix.city:LoadCity(id, tbl)
if isnumber(id) then id = tostring(id) end
local city = setmetatable({
id = id,
credits = tbl.credits,
type = tbl.type,
items = tbl.items,
loan = tbl.loan
}, ix.meta.city)
ix.city.list[id] = city
return city
end
function ix.city:LoadMainCity(tbl)
local mainCity = ix.city.main and ix.city.main or setmetatable({
id = "1",
credits = tbl.credits,
type = {},
items = tbl.items,
loan = tbl.loan
}, ix.meta.city)
ix.city.main = mainCity
return mainCity
end
function ix.city:GetCity(id)
return id != "1" and ix.city.list[id] or ix.city:GetMainCity()
end
function ix.city:Remove(id)
if ix.city.list[id] then ix.city.list[id] = nil end
ix.city:DeleteCity(id)
end
function ix.city:IsMain(city)
if isstring(city) and city == "1" or city == ix.city.main then
return true
end
return false
end
function ix.city:GetMainCity()
return ix.city.main
end
function ix.city.types:RegisterType(name, tbl)
if ix.city.types.list[name] then return end
-- Rates here stands for time in hours.
local type = {
name = name,
itemsHighRate = tbl.itemsHighRate,
itemsLowRate = tbl.itemsLowRate,
itemsAverageRate = tbl.itemsAverageRate,
highRateProduction = tbl.highRateProduction,
lowRateProduction = tbl.lowRateProduction,
averageRateProduction = tbl.averageRateProduction,
passiveIncome = tbl.passiveIncome,
passiveIncomeRate = tbl.passiveIncomeRate
}
ix.city.types.list[name] = type
ix.city:AddTypeData(name, type)
end
function ix.city:AddCityData(id, city)
local queryAdd = mysql:Insert("ix_cities")
queryAdd:Insert("ct_id", id)
queryAdd:Insert("ct_credits", city:GetCredits())
queryAdd:Insert("ct_type", util.TableToJSON(city:GetType()))
queryAdd:Insert("ct_items", util.TableToJSON(city.items))
queryAdd:Insert("ct_loan", city:GetLoan())
queryAdd:Insert("ct_loanRate", city.loanRate)
queryAdd:Execute()
end
function ix.city:UpdateCity(id)
if !isstring(id) then id = id:GetID() end
local city = id != "1" and ix.city.list[id] or ix.city.main
local queryUpdate = mysql:Update("ix_cities")
queryUpdate:Where("ct_id", id)
queryUpdate:Update("ct_credits", city:GetCredits())
queryUpdate:Update("ct_type", util.TableToJSON(city:GetType() or {}))
queryUpdate:Update("ct_items", util.TableToJSON(city.items))
queryUpdate:Update("ct_loan", city:GetLoan())
queryUpdate:Update("ct_loanRate", city.loanRate)
queryUpdate:Execute()
-- update main city on all terminals (main cities are refreshing automatically)
if id == "1" then
ix.city:UpdateCWUTerminals()
end
end
function ix.city:UpdateCWUTerminals()
local dataToSend = table.Copy(ix.city.main)
dataToSend.factionBudgets = ix.factionBudget.list
for _, terminal in pairs(ents.FindByClass("ix_cwuterminal")) do
local client = terminal:GetUsedBy()
if client and client:IsPlayer() and terminal.curGenData then
net.Start("ix.terminal.UpdateCWUTerminals")
net.WriteString(util.TableToJSON(dataToSend))
net.WriteEntity(terminal)
net.Send(terminal:GetUsedBy())
end
end
end
-- debug function
function ix.city:LoadCityData(id)
if !isstring(id) then id = id:GetID() end
local queryLoad = mysql:Select("ix_cities")
queryLoad:Where("ct_id", id)
queryLoad:Callback(function(dataSelectResult)
if (!istable(dataSelectResult) or #dataSelectResult == 0) then
return
end
print(id .. ": DATA SELECT RESULT")
PrintTable(dataSelectResult)
return dataSelectResult
end)
queryLoad:Execute()
end
function ix.city:DeleteCity(id)
if !isstring(id) then id = id:GetID() end
local queryDelete = mysql:Delete("ix_cities")
queryDelete:Where("ct_id", id)
queryDelete:Execute()
end
-- for debug and develop only
function ix.city:PurgeCities()
local queryPurge = mysql:Drop("ix_cities")
queryPurge:Execute()
end
function ix.city:LoadTypes()
local queryLoad = mysql:Select("ix_citytypes")
queryLoad:Callback(function(dataSelectResult)
if (!istable(dataSelectResult) or #dataSelectResult == 0) then
return
end
return ix.city:InitializeTypes(dataSelectResult)
end)
queryLoad:Execute()
end
function ix.city:LoadCities()
local queryLoad = mysql:Select("ix_cities")
queryLoad:Callback(function(dataSelectResult)
if (!istable(dataSelectResult) or #dataSelectResult == 0) then
return
end
return ix.city:InitializeCities(dataSelectResult)
end)
queryLoad:Execute()
end
function ix.city:InitializeCities(cities)
for _, city in pairs(cities) do
local cityData = {}
cityData.id = isstring(city["ct_id"]) and city["ct_id"] or tostring(city["ct_id"])
cityData.items = util.JSONToTable(city["ct_items"]) or {}
cityData.type = util.JSONToTable(city["ct_type"]) or {}
cityData.credits = tonumber(city["ct_credits"])
cityData.loan = tonumber(city["ct_loan"])
cityData.loanRate = tonumber(city["ct_loanRate"])
if cityData.id == "1" then
ix.city:LoadMainCity(cityData)
else
ix.city:LoadCity(cityData.id, cityData)
end
end
end
function ix.city:AddTypeData(name, typeData)
local queryAdd = mysql:Insert("ix_citytypes")
queryAdd:Insert("t_name", name)
queryAdd:Insert("t_data", util.TableToJSON(typeData))
queryAdd:Execute()
end
function ix.city:UpdateType(name)
if !isstring(name) then name = tostring(name) end
local queryUpdate = mysql:Update("ix_citytypes")
queryUpdate:Where("t_name", name)
queryUpdate:Update("t_data", util.TableToJSON(ix.city.types.list[name]))
queryUpdate:Execute()
end
-- make sure to include data / metaobject in global table later
function ix.city:LoadTypeData(name)
local queryLoad = mysql:Select("ix_citytypes")
queryLoad:Where("t_name", name)
queryLoad:Callback(function(dataSelectResult)
if (!istable(dataSelectResult) or #dataSelectResult == 0) then
return
end
return dataSelectResult
end)
queryLoad:Execute()
end
function ix.city:DeleteType(name)
local queryDelete = mysql:Delete("ix_citytypes")
queryDelete:Where("t_name", name)
queryDelete:Execute()
end
function ix.city:InitializeTypes(types)
for _, type in pairs(types) do
local typeData = {}
typeData.name = type["t_name"]
typeData.data = util.JSONToTable(type["t_data"]) or {}
ix.city:LoadType(typeData.name, typeData.data)
end
end
-- for debug and develop only
function ix.city:PurgeTypes()
local queryPurge = mysql:Drop("ix_citytypes")
queryPurge:Execute()
end
-- cwu terminal related
function ix.city:IsAuthorized(client, ent)
if ent and (ent:GetUsedBy() == client and ent.curGenData and ent:IsFullyAuthed() and (client:EyePos():DistToSqr(ent:GetPos()) < 10000)) then
return true
end
return false
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/
--]]
function ix.factionBudget:GetFBCredits(id)
return ix.factionBudget:GetFB(id).credits
end
function ix.factionBudget:SetFBCredits(id, credits)
ix.factionBudget.list[id].credits = math.Clamp(credits, 0, 50000)
end
function ix.factionBudget:AddFBCredits(id, credits)
local curCreds = ix.factionBudget:GetFBCredits(id)
ix.factionBudget.list[id].credits = math.Clamp(curCreds + credits, 0, 50000)
end
function ix.factionBudget:TakeFBCredits(id, credits)
local curCreds = ix.factionBudget:GetFBCredits(id)
ix.factionBudget.list[id].credits = math.Clamp(curCreds - credits, 0, 50000)
end
function ix.factionBudget:HasCredits(id, credits)
local curCreds = ix.factionBudget:GetFBCredits(id)
if curCreds >= credits then
return true
end
return false
end
function ix.factionBudget:SaveBudgets()
ix.data.Set("factionBudgets", ix.factionBudget.list, false, true)
ix.city:UpdateCWUTerminals()
end
function ix.factionBudget:LoadBudgets()
ix.factionBudget:InitializeFactionBudgets()
local budgetList = ix.data.Get("factionBudgets", false, false, true)
if budgetList then
for k, v in pairs(budgetList) do
if ix.factionBudget.list[k] then
ix.factionBudget.list[k] = v
end
end
end
end

View File

@@ -0,0 +1,341 @@
--[[
| 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 math = math
local ix = ix
local pairs = pairs
local table = table
local istable = istable
local string = string
local CITY = ix.meta.city or {}
CITY.__index = CITY
CITY.id = 0
CITY.credits = 0
CITY.type = {}
CITY.items = {}
CITY.loan = 0
CITY.loanRate = 0
function CITY:__tostring()
return "CITY-" .. self.id
end
function CITY:__eq(other)
return self:GetID() == other:GetID()
end
function CITY:GetID()
return self.id
end
function CITY:OnCreated()
self:SetType(self.type, true)
end
function CITY:TakeCredits(amount)
self.credits = math.Clamp(self.credits - amount, -ix.config.Get("minusCityCap", 0), 999999)
ix.city:UpdateCity(self)
end
function CITY:AddCredits(amount)
self.credits = math.Clamp(self.credits + amount, -ix.config.Get("minusCityCap", 0), 999999)
ix.city:UpdateCity(self)
end
function CITY:SetCredits(amount)
self.credits = math.Clamp(amount, -ix.config.Get("minusCityCap", 0), 999999)
ix.city:UpdateCity(self)
end
function CITY:HasCredits(amount)
local creditsToCheck = self.credits
if creditsToCheck < 0 and creditsToCheck != -ix.config.Get("minusCityCap", 0) then
creditsToCheck = ix.config.Get("minusCityCap", 0) + creditsToCheck
end
if creditsToCheck >= amount then
return true
end
return false
end
function CITY:GetCredits()
return self.credits
end
function CITY:GetLoan()
return self.loan
end
function CITY:SetLoan(amount)
self.loan = math.Clamp(amount, 0, 999999)
ix.city:UpdateCity(self)
end
function CITY:AddLoan(amount)
self.loan = math.Clamp(self.loan + amount, 0, 999999)
self:AddCredits(amount)
ix.city:UpdateCity(self)
end
function CITY:TakeLoan(amount)
self.loan = math.Clamp(self.loan - amount, 0, 999999)
ix.city:UpdateCity(self)
end
function CITY:PayLoan(amount)
if !self:HasCredits(amount) then return "Your city don't have enough credits." end
self:TakeLoan(amount)
self:TakeCredits(amount)
end
function CITY:IsMain()
return self:GetID() == "1"
end
function CITY:AddItem(item, amount, price, priceMulptiplicationTD, priceReductionTD, priceMul, priceDiv)
if self.items[item] then
amount = self.items[item].amount + amount
end
if !self:IsMain() then
self.items[item] = {
amount = amount,
price = price and price or self.items[item] and self.items[item].price and self.items[item].price or 0,
priceMulptiplicationTD = priceMulptiplicationTD and priceMulptiplicationTD or self.items[item] and self.items[item].priceMulptiplicationTD or 10,
priceReductionTD = priceReductionTD and priceReductionTD or self.items[item] and self.items[item].priceReductionTD or 90,
priceMul = priceMul and priceMul or self.items[item] and self.items[item].priceMul or 2,
priceDiv = priceDiv and priceDiv or self.items[item] and self.items[item].priceDiv or 2
}
else
self.items[item] = {
amount = amount
}
end
ix.city:UpdateCity(self)
end
function CITY:HasItem(item)
if self.items[item] and self.items[item].amount > 0 then
return true
end
return false
end
function CITY:RemoveItem(item, amount)
amount = amount or 1
if self.items[item] and (self.items[item].amount - amount) >= 0 then
self.items[item].amount = self.items[item].amount - amount
end
end
function CITY:OnItemTaken(item) end
function CITY:TakeItem(item, amount)
if self:HasItem(item) then
self:RemoveItem(item, amount)
self:OnItemTaken(item)
end
ix.city:UpdateCity(self)
end
function CITY:GetItemPrice(itemTbl)
if itemTbl.priceMulptiplicationTD and itemTbl.amount <= itemTbl.priceMulptiplicationTD then
return math.ceil(itemTbl.price * itemTbl.priceMul)
elseif itemTbl.priceReductionTD and itemTbl.amount >= itemTbl.priceReductionTD then
return math.ceil(itemTbl.price / itemTbl.priceDiv)
else
return itemTbl.price
end
end
function CITY:SellItems(item, fund, amount)
local itemTbl = self.items[item]
local fundItem = fund.items[item]
local cityStr = "CITY-" .. self.id
local fundStr = "CITY-" .. fund.id
if !itemTbl or itemTbl.amount <= 0 then
return cityStr .. " don't have this: '" .. ix.item.list[item].name .. "' with amount of " .. amount
end
if fund.id != "1" and !fundItem then
return fundStr .. " don't want to make any deals with this item."
end
local price = self.id != "1" and self:GetItemPrice(itemTbl) or fund:GetItemPrice(fundItem)
if !fund:HasCredits(price * amount) then
return fundStr .. " don't have enough credits. (Available at this moment: " .. fund:GetCredits() .. ")"
end
fund:AddItem(item, amount)
fund:TakeCredits(price * amount)
self:AddCredits(price * amount)
self:TakeItem(item, amount)
ix.city:UpdateCity(self)
return price * amount
end
function CITY:AutoSell(item, amount)
local citiesWithItem = {}
local selectedCity = false
for cityID, city in pairs(ix.city.list) do
if city.items[item] then
local itemPrice = self:GetItemPrice(city.items[item])
if city:HasCredits(itemPrice) then
citiesWithItem[#citiesWithItem + 1] = {
price = itemPrice,
cityID = cityID,
}
end
end
end
table.sort( citiesWithItem, function(a, b) return a.price > b.price end )
if #citiesWithItem != 0 and citiesWithItem[#citiesWithItem] then
selectedCity = citiesWithItem[1].cityID
else
return "Can't find city to sell."
end
local sellItems = self:SellItems(item, ix.city.list[selectedCity], amount)
return sellItems
end
function CITY:ExportItems(item, city, amount)
end
function CITY:GetItems()
return self.items
end
function CITY:GetType()
return self.type
end
function CITY:SetType(tbl, noUpdate)
self.type = tbl
self.type.cIncomeProgress = 0
self.type.productionProgress = {
lowRateProduction = 0,
averageRateProduction = 0,
highRateProduction = 0
}
if !noUpdate then
ix.city:UpdateCity(self)
end
end
function CITY:IncrementLoanProgress()
if !self:IsMain() then return end
if self:GetCredits() <= 0 then return end
self.loanRate = self.loanRate + 1
if self.loanRate >= 24 then
local credPercent = self:GetCredits() / 100
self:TakeCredits(math.Round(credPercent * ix.config.Get("loanPercent")))
self.loanRate = 0
end
ix.city:UpdateCity(self)
end
function CITY:IncrementIncomeProgress()
if !self.type or !istable(self.type) or table.IsEmpty(self.type) then return end
self.type.cIncomeProgress = self.type.cIncomeProgress + 1
if self.type.cIncomeProgress >= self.type.passiveIncomeRate then
self:AddCredits(self.type.passiveIncome)
self.type.cIncomeProgress = 0
end
ix.city:UpdateCity(self)
end
function CITY:IncrementProductionProgress()
if !self.type or !istable(self.type) or table.IsEmpty(self.type) then return end
for i, production in pairs(self.type.productionProgress) do
self.type.productionProgress[i] = self.type.productionProgress[i] + 1
if self.type.productionProgress[i] >= self.type[i] then
self:HandleItemProduction(i)
self.type.productionProgress[i] = 0
end
end
ix.city:UpdateCity(self)
end
function CITY:HandleItemConsumption()
if !self.type or !istable(self.type) or table.IsEmpty(self.type) then return end
if table.IsEmpty(self.items) then return end
local range = {ix.config.Get("randItemDeletionAmountRangeMin"), ix.config.Get("randItemDeletionAmountRangeMax")}
local difItemsToTake = ix.config.Get("randItemDeletions")
for i = 1, difItemsToTake do
local itemsAmountToTake = math.random(range[1], range[2])
local _, itemID = table.Random(self.items)
self:TakeItem(itemID, itemsAmountToTake)
end
end
function CITY:HandleItemProduction(rate)
local itemTable
local range
if string.match(rate, "high") then
itemTable = self.type.itemsHighRate
range = {ix.config.Get("highItemProductionMinRange"), ix.config.Get("highItemProductionMaxRange")}
elseif string.match(rate, "average") then
itemTable = self.type.itemsAverageRate
range = {ix.config.Get("averageItemProductionMinRange"), ix.config.Get("averageItemProductionMaxRange")}
elseif string.match(rate, "low") then
itemTable = self.type.itemsLowRate
range = {ix.config.Get("lowItemProductionMinRange"), ix.config.Get("lowItemProductionMaxRange")}
end
if !istable(itemTable) or !range then return end
local itemsProduced = math.random(range[1], range[2])
for item, _ in pairs(itemTable) do
if self.items[item] then
self:AddItem(item, itemsProduced)
end
end
end
ix.meta.city = CITY

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/
--]]
net.Receive("ix.city.CreateCFEditor", function()
vgui.Create("ixFundManager")
end)
net.Receive("ix.city.SyncCityStock", function()
local items = util.JSONToTable(net.ReadString())
if !istable(ix.city.main) then
ix.city.main = {}
end
ix.city.main.items = items
if ix.gui.barteringpanel then
if !ix.gui.barteringpanel.built then
ix.gui.barteringpanel:Proceed()
end
end
end)
net.Receive("ix.city.RequestTypes", function()
local parent = ix.gui.fundManager
if !parent then return end
local typeTbl = util.JSONToTable(net.ReadString())
parent.types = typeTbl
end)
net.Receive("ix.city.PopulateFunds", function()
local parent = ix.gui.fundManager
if !parent then return end
local cityTbl = util.JSONToTable(net.ReadString())
parent:Populate(cityTbl)
end)
net.Receive("ix.city.RequestUpdateTypes", function()
local parent = ix.gui.ctEditor
if !parent then return end
local typeTbl = util.JSONToTable(net.ReadString())
parent:UpdateTypes(typeTbl)
end)
net.Receive("ix.city.RequestUpdateCities", function()
local parent = ix.gui.fundManager
if !parent then return end
local cityTbl = util.JSONToTable(net.ReadString())
parent:UpdateCities(cityTbl)
end)

View File

@@ -0,0 +1,585 @@
--[[
| 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 util = util
local net = net
local ix = ix
local tonumber = tonumber
local istable = istable
local isnumber = isnumber
local pairs = pairs
local CAMI = CAMI
-- one day i definitely should re-do the networking here..
util.AddNetworkString("ix.city.CreateCFEditor")
util.AddNetworkString("ix.city.SyncCityStock")
util.AddNetworkString("ix.city.PopulateFunds")
util.AddNetworkString("ix.city.RequestTypes")
util.AddNetworkString("ix.city.RequestUpdateTypes")
util.AddNetworkString("ix.city.RequestUpdateCities")
util.AddNetworkString("ix.city.CreateType")
util.AddNetworkString("ix.city.CreateCity")
util.AddNetworkString("ix.city.UpdateType")
util.AddNetworkString("ix.city.UpdateCity")
util.AddNetworkString("ix.city.RemoveType")
util.AddNetworkString("ix.city.RemoveCity")
util.AddNetworkString("ix.city.Autosell")
util.AddNetworkString("ix.city.Sell")
util.AddNetworkString("ix.city.TakeItem")
util.AddNetworkString("ix.city.BuyCart")
util.AddNetworkString("ix.city.WithdrawCredits")
util.AddNetworkString("ix.city.DepositCredits")
util.AddNetworkString("ix.city.PayLoan")
util.AddNetworkString("ix.city.TakeLoan")
util.AddNetworkString("ix.city.SetFactionBudget")
util.AddNetworkString("ix.city.WithdrawFactionBudget")
util.AddNetworkString("ix.city.DepositFactionBudget")
net.Receive("ix.city.SyncCityStock", function(len, client)
ix.city:SyncCityStock(client)
end)
net.Receive("ix.city.DepositFactionBudget", function(len, client)
local budgetID = net.ReadString()
local credits = net.ReadInt(15)
local ent = net.ReadEntity()
if !ent then return end
if !credits then return end
if !budgetID then return end
if (!ix.city:IsAuthorized(client, ent)) then return end
if (!ix.city:IsAccessable(ix.item.instances[ent:GetCWUCard()], "budgetInteraction") and !ent.curGenData.isCCA) then
return client:NotifyLocalized("No access.")
end
local fName = ix.factionBudget.list[budgetID].name
local idCard = ix.item.instances[ent:GetCID()]
if idCard:HasCredits(credits) then
ix.factionBudget:AddFBCredits(budgetID, credits)
idCard:TakeCredits(credits, "CWU terminal", "Credits deposited in faction budget: "..fName)
else
return client:NotifyLocalized("You don't have this amount of credits.")
end
ix.factionBudget:SaveBudgets()
client:NotifyLocalized("Success!")
ix.log.Add(client, "factionBudgetCWU", "deposited", credits, fName)
end)
net.Receive("ix.city.WithdrawFactionBudget", function(len, client)
local budgetID = net.ReadString()
local credits = net.ReadInt(15)
local ent = net.ReadEntity()
if !ent then return end
if !credits then return end
if !budgetID then return end
if (!ix.city:IsAuthorized(client, ent)) then return end
if (!ix.city:IsAccessable(ix.item.instances[ent:GetCWUCard()], "budgetInteraction") and !ent.curGenData.isCCA) then
return client:NotifyLocalized("No access.")
end
local fName = ix.factionBudget.list[budgetID].name
local idCard = ix.item.instances[ent:GetCID()]
if ix.factionBudget:HasCredits(budgetID, credits) then
ix.factionBudget:TakeFBCredits(budgetID, credits)
idCard:GiveCredits(credits, "CWU terminal", "Credits withdrawen from faction budget: "..fName)
else
return client:NotifyLocalized("Faction budget don't have this amount of credits.")
end
ix.factionBudget:SaveBudgets()
client:NotifyLocalized("Success!")
ix.log.Add(client, "factionBudgetCWU", "withdrew", credits, fName)
end)
net.Receive("ix.city.TakeItem", function(len, client)
local incomingData = net.ReadString()
local itemTbl = ix.item.list[incomingData]
local ent = net.ReadEntity()
local isCombine = ent.curGenData and ent.curGenData.combine or false
if !ent then return end
if !incomingData then return end
if !ent.curGenData then return end
if (!ix.city:IsAuthorized(client, ent)) then return end
if (!itemTbl) then
ix.city.main.items[incomingData] = nil
return
end
if (ix.city:IsCombineRestricted(incomingData) or ix.city:IsCombineRestricted(itemTbl.category)) and (!isCombine) then
return client:NotifyLocalized("You are not allowed to take this item out of stock.")
end
if (!isCombine) then
if (!ix.city:IsAccessable(ix.item.instances[ent:GetCWUCard()], "stockInteraction") and !ent.curGenData.isCCA) then
return client:NotifyLocalized("No access.")
end
end
if ix.city.main:HasItem(incomingData) then
local charID = ent.curGenData.id
local char = ix.char.loaded[ent.curGenData.id]
local charName = ent.curGenData.name
if char then
char:SetPurchasedItems(incomingData, 1)
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
if purchasedItems[incomingData] then
purchasedItems[incomingData] = purchasedItems[incomingData] + 1
else
purchasedItems[incomingData] = 1
end
local updateQuery = mysql:Update("ix_characters_data")
updateQuery:Update("data", util.TableToJSON(purchasedItems))
updateQuery:Where("id", tonumber(charID))
updateQuery:Where("key", "purchasedItems")
updateQuery:Execute()
end)
dataSelect:Execute()
end
ix.city.main:TakeItem(incomingData)
client:NotifyLocalized("Item added to pickup terminal.")
ix.log.Add(client, "stockInteraction", incomingData)
ix.combineNotify:AddNotification("FND:// ".. charName .. " took "..ix.item.list[incomingData].name.." from city stock", nil, client)
end
end)
net.Receive("ix.city.Autosell", function(len, client)
local incomingData = net.ReadString()
local ent = net.ReadEntity()
local isCombine = ent.curGenData and ent.curGenData.combine or false
if !ent then return end
if !incomingData then return end
if !ent.curGenData then return end
if (!ix.city:IsAuthorized(client, ent)) then return end
if (!isCombine) then
if (!ix.city:IsAccessable(ix.item.instances[ent:GetCWUCard()], "marketInteraction") and !ent.curGenData.isCCA) then
return client:NotifyLocalized("No access.")
end
end
local charName = ent.curGenData.name
local item = util.JSONToTable(incomingData)
local successCheck = ix.city.main:AutoSell(item.itemID, item.amount)
if successCheck and !isnumber(successCheck) then
client:NotifyLocalized("Can't find any city to sell this item.")
else
ix.combineNotify:AddNotification("FND:// ".. charName .. " has sold 1 items(s) from city stock: "..ix.item.list[item.itemID].name, nil, client)
ix.log.Add(client, "marketInteraction", "sold", 1, item.itemID, successCheck)
end
end)
net.Receive("ix.city.Sell", function(len, client)
local incomingData = net.ReadString()
local ent = net.ReadEntity()
local isCombine = ent.curGenData and ent.curGenData.combine or false
if !ent then return end
if !incomingData then return end
if !ent.curGenData then return end
if (!ix.city:IsAuthorized(client, ent)) then return end
if (!isCombine) then
if (!ix.city:IsAccessable(ix.item.instances[ent:GetCWUCard()], "marketInteraction") and !ent.curGenData.isCCA) then
return client:NotifyLocalized("No access.")
end
end
local charName = ent.curGenData.name
local data = util.JSONToTable(incomingData)
local successCheck = ix.city.main:SellItems(data.itemID, ix.city.list[data.cityID], data.amount)
if successCheck and !isnumber(successCheck) then
client:NotifyLocalized(successCheck)
else
client:NotifyLocalized("Success!")
ix.combineNotify:AddNotification("FND:// ".. charName .. " has sold "..data.amount.." items(s) from city stock: "..ix.item.list[data.itemID].name, nil, client)
ix.log.Add(client, "marketInteraction", "sold", data.amount, data.itemID, successCheck)
end
end)
net.Receive("ix.city.BuyCart", function(len, client)
local incomingData = net.ReadString()
local ent = net.ReadEntity()
local isCombine = ent.curGenData and ent.curGenData.combine or false
if !ent then return end
if !incomingData then return end
if !ent.curGenData then return end
if (!ix.city:IsAuthorized(client, ent)) then return end
if (!isCombine) then
if (!ix.city:IsAccessable(ix.item.instances[ent:GetCWUCard()], "marketInteraction") and !ent.curGenData.isCCA) then
return client:NotifyLocalized("No access.")
end
end
local charName = ent.curGenData.name
local cart = util.JSONToTable(incomingData)
local successCheck
for _, cartSlot in pairs(cart) do
local item = cartSlot.itemData.id
local itemAmount = cartSlot.amount
local city = ix.city.list[cartSlot.city]
successCheck = city:SellItems(item, ix.city.main, itemAmount)
if successCheck and !isnumber(successCheck) then
client:NotifyLocalized(successCheck)
else
ix.combineNotify:AddNotification("FND:// ".. charName .. " has sold "..itemAmount.." items(s) from city stock: "..ix.item.list[item].name, nil, client)
ix.log.Add(client, "marketInteraction", "bought", itemAmount, item, successCheck)
end
end
if !successCheck or isnumber(successCheck) then
client:NotifyLocalized("Purchase successful!")
end
end)
net.Receive("ix.city.WithdrawCredits", function(len, client)
local incomingData = net.ReadInt(15)
local ent = net.ReadEntity()
local isCombine = ent.curGenData and ent.curGenData.combine or false
if !ent then return end
if !incomingData then return end
if !ent.curGenData then return end
if (!ix.city:IsAuthorized(client, ent)) then return end
if (!isCombine) then
if (!ix.city:IsAccessable(ix.item.instances[ent:GetCWUCard()], "creditInteraction") and !ent.curGenData.isCCA) then
return client:NotifyLocalized("No access.")
end
end
if ix.city.main:HasCredits(incomingData) then
local charName = ent.curGenData.name
local idCard = ix.item.instances[ent:GetCID()]
idCard:GiveCredits(incomingData, "CWU terminal", "Credits withdrawen from city fund.")
ix.city.main:TakeCredits(incomingData)
ix.combineNotify:AddNotification("FND:// ".. charName .. " withdrew " .. incomingData .. " credits from city fund", color_red, client)
ix.log.Add(client, "cityFundInteraction", "withdrew", incomingData)
else
return client:NotifyLocalized("City don't have enough credits.")
end
end)
net.Receive("ix.city.DepositCredits", function(len, client)
local incomingData = net.ReadInt(15)
local ent = net.ReadEntity()
local isCombine = ent.curGenData and ent.curGenData.combine or false
if !ent then return end
if !incomingData then return end
if !ent.curGenData then return end
if (!ix.city:IsAuthorized(client, ent)) then return end
if (!isCombine) then
if (!ix.city:IsAccessable(ix.item.instances[ent:GetCWUCard()], "creditInteraction") and !ent.curGenData.isCCA) then
return client:NotifyLocalized("No access.")
end
end
local idCard = ix.item.instances[ent:GetCID()]
if idCard:HasCredits(incomingData) then
local charName = ent.curGenData.name
idCard:TakeCredits(incomingData, "CWU terminal", "Credits deposited in city fund.")
ix.city.main:AddCredits(incomingData)
ix.combineNotify:AddNotification("FND:// ".. charName .. " deposited " .. incomingData .. " credits in city fund", color_green, client)
ix.log.Add(client, "cityFundInteraction", "deposited", incomingData)
else
return client:NotifyLocalized("You don't have enough credits.")
end
end)
net.Receive("ix.city.PayLoan", function(len, client)
local incomingData = net.ReadInt(15)
local ent = net.ReadEntity()
local isCombine = ent.curGenData and ent.curGenData.combine or false
if !ent then return end
if !incomingData then return end
if !ent.curGenData then return end
if (!ix.city:IsAuthorized(client, ent)) then return end
if (!isCombine) then
if (!ix.city:IsAccessable(ix.item.instances[ent:GetCWUCard()], "creditInteraction") and !ent.curGenData.isCCA) then
return client:NotifyLocalized("No access.")
end
end
if ix.city.main:HasCredits(incomingData) then
local charName = ent.curGenData.name
ix.city.main:PayLoan(incomingData)
ix.combineNotify:AddNotification("FND:// ".. charName .. " paid loan with " .. incomingData .. " credits taken from city fund", color_green, client)
ix.log.Add(client, "cityFundInteraction", "paid loan with", incomingData)
else
return client:NotifyLocalized("City don't have enough credits.")
end
end)
net.Receive("ix.city.TakeLoan", function(len, client)
local incomingData = net.ReadInt(15)
local ent = net.ReadEntity()
local isCombine = ent.curGenData and ent.curGenData.combine or false
if !ent then return end
if !incomingData then return end
if !ent.curGenData then return end
if (!ix.city:IsAuthorized(client, ent)) then return end
if (!isCombine) then
if (!ix.city:IsAccessable(ix.item.instances[ent:GetCWUCard()], "creditInteraction") and !ent.curGenData.isCCA) then
return client:NotifyLocalized("No access.")
end
end
local charName = ent.curGenData.name
ix.city.main:AddLoan(incomingData)
ix.combineNotify:AddNotification("FND:// ".. charName .. " took out a " .. incomingData .. " credits loan", color_red, client)
ix.log.Add(client, "cityFundInteraction", "took out loan: ", incomingData)
end)
net.Receive("ix.city.SetFactionBudget", function(len, client)
local incomingData = net.ReadString()
local ent = net.ReadEntity()
local isCombine = ent.curGenData and ent.curGenData.combine or false
if !ent then return end
if !incomingData then return end
if !ent.curGenData then return end
if (!ix.city:IsAuthorized(client, ent)) then return end
if (!isCombine) then
if (!ix.city:IsAccessable(ix.item.instances[ent:GetCWUCard()], "creditInteraction") and !ent.curGenData.isCCA) then
return client:NotifyLocalized("No access.")
end
end
incomingData = util.JSONToTable(incomingData)
local budget = ix.factionBudget:GetFB(incomingData.budgetID)
local budgetName = budget.name
local newBudget = incomingData.newBudget
local oldBudget = budget.credits
local remains = oldBudget - newBudget
if remains < 0 and !ix.city.main:HasCredits(-remains) then return "No credits" end
budget.credits = newBudget
ix.factionBudget:SaveBudgets()
if remains > 0 then
ix.city.main:AddCredits(remains)
else
ix.city.main:TakeCredits(-remains)
end
ix.log.Add(client, "factionBudget", budgetName, oldBudget, newBudget)
end)
net.Receive("ix.city.RequestUpdateTypes", function(len, client)
if (!CAMI.PlayerHasAccess(client, "Helix - Manage City Fund")) then return end
net.Start("ix.city.RequestUpdateTypes")
net.WriteString(util.TableToJSON(ix.city.types.list))
net.Send(client)
end)
net.Receive("ix.city.RequestUpdateCities", function(len, client)
if (!CAMI.PlayerHasAccess(client, "Helix - Manage City Fund")) then return end
local cityTbl = {}
for index, city in pairs(ix.city.list) do
cityTbl[index] = city
end
cityTbl["1"] = ix.city.main
net.Start("ix.city.RequestUpdateCities")
net.WriteString(util.TableToJSON(cityTbl))
net.Send(client)
end)
net.Receive("ix.city.RemoveType", function(len, client)
if (!CAMI.PlayerHasAccess(client, "Helix - Manage City Fund")) then return end
local tID = net.ReadString()
if (ix.city.types.list[tID]) then
ix.city.types.list[tID] = nil
ix.city:DeleteType(tID)
for cityID, city in pairs(ix.city.list) do
if city.type.name == tID then
city.type = false
ix.city:UpdateCity(cityID)
end
end
end
end)
net.Receive("ix.city.RemoveCity", function(len, client)
if (!CAMI.PlayerHasAccess(client, "Helix - Manage City Fund")) then return end
local cID = net.ReadString()
if (ix.city.list[cID]) then
ix.city.list[cID] = nil
ix.city:DeleteCity(cID)
end
end)
net.Receive("ix.city.CreateType", function(len, client)
if (!CAMI.PlayerHasAccess(client, "Helix - Manage City Fund")) then return end
local tID = net.ReadString()
if (!ix.city.types.list[tID]) then
ix.city.types:RegisterType(tID, {
name = tID,
itemsHighRate = {},
itemsLowRate = {},
itemsAverageRate = {},
highRateProduction = 1,
lowRateProduction = 3,
averageRateProduction = 2,
passiveIncome = 100,
passiveIncomeRate = 1
})
end
end)
net.Receive("ix.city.CreateCity", function(len, client)
if (!CAMI.PlayerHasAccess(client, "Helix - Manage City Fund")) then return end
local cityID = net.ReadString()
local cityType = net.ReadString()
ix.city:CreateCity(cityID, cityType)
end)
local function CheckItemRates(actualTD)
if actualTD.highRateProduction < actualTD.averageRateProduction and
actualTD.highRateProduction < actualTD.lowRateProduction and
actualTD.averageRateProduction < actualTD.lowRateProduction then
return true
end
return false
end
net.Receive("ix.city.UpdateType", function(len, client)
if (!CAMI.PlayerHasAccess(client, "Helix - Manage City Fund")) then return end
local incomingData = net.ReadString()
local tTbl = util.JSONToTable(incomingData)
if !CheckItemRates(tTbl) then
return
end
if ix.city.types.list[tTbl.name] then
ix.city.types.list[tTbl.name].itemsHighRate = tTbl.itemsHighRate or {}
ix.city.types.list[tTbl.name].itemsLowRate = tTbl.itemsLowRate or {}
ix.city.types.list[tTbl.name].itemsAverageRate = tTbl.itemsAverageRate or {}
ix.city.types.list[tTbl.name].highRateProduction = tTbl.highRateProduction or 1
ix.city.types.list[tTbl.name].lowRateProduction = tTbl.lowRateProduction or 3
ix.city.types.list[tTbl.name].averageRateProduction = tTbl.averageRateProduction or 2
ix.city.types.list[tTbl.name].passiveIncome = tTbl.passiveIncome or 100
ix.city.types.list[tTbl.name].passiveIncomeRate = tTbl.passiveIncomeRate or 1
end
ix.city:UpdateType(tTbl.name)
end)
local function ValidateCityData(cTbl, client)
for item, itemData in pairs(cTbl.items) do
itemData.amount = isnumber(itemData.amount) and itemData.amount or tonumber(itemData.amount) or 1
itemData.price = isnumber(itemData.price) and itemData.price or tonumber(itemData.price) or 50
itemData.priceDiv = isnumber(itemData.priceDiv) and itemData.priceDiv or tonumber(itemData.priceDiv) or 2
itemData.priceMul = isnumber(itemData.priceMul) and itemData.priceMul or tonumber(itemData.priceMul) or 2
itemData.priceMulptiplicationTD = isnumber(itemData.priceMulptiplicationTD) and itemData.priceMulptiplicationTD or tonumber(itemData.priceMulptiplicationTD) or 10
itemData.priceReductionTD = isnumber(itemData.priceReductionTD) and itemData.priceReductionTD or tonumber(itemData.priceReductionTD) or 90
end
end
net.Receive("ix.city.UpdateCity", function(len, client)
if (!CAMI.PlayerHasAccess(client, "Helix - Manage City Fund")) then return end
local incomingData = net.ReadString()
local isMain = net.ReadBool()
local cTbl = util.JSONToTable(incomingData)
ValidateCityData(cTbl, client)
for item, itemData in pairs(cTbl.items) do
itemData.amount = itemData.amount or 0
itemData.price = itemData.price or 0
itemData.priceDiv = itemData.priceDiv or 2
itemData.priceMul = itemData.priceMul or 2
itemData.priceMulptiplicationTD = itemData.priceMulptiplicationTD or 10
itemData.priceReductionTD = itemData.priceReductionTD or 90
end
if ix.city.list[cTbl.id] and !isMain then
ix.city.list[cTbl.id].credits = tonumber(cTbl.credits) or 0
ix.city.list[cTbl.id].items = cTbl.items or {}
ix.city.list[cTbl.id].loan = tonumber(cTbl.loan) or 0
if ix.city.types.list[cTbl.type.name] then
ix.city.list[cTbl.id].type = cTbl.type or {}
end
ix.city:UpdateCity(cTbl.id)
elseif isMain then
if istable(cTbl.items) then
for itemID, item in pairs(cTbl.items) do
cTbl.items[itemID] = {amount = item.amount}
end
ix.city.main.items = cTbl.items
end
ix.city.main.credits = tonumber(cTbl.credits)
ix.city.main.loan = tonumber(cTbl.loan)
ix.city:UpdateCity(cTbl.id)
end
end)
net.Receive("ix.city.PopulateFunds", function(len, client)
if (!CAMI.PlayerHasAccess(client, "Helix - Manage City Fund")) then return end
local cityTbl = {}
for index, city in pairs(ix.city.list) do
cityTbl[index] = city
end
cityTbl["1"] = ix.city.main
local typeTbl = {}
for index, type in pairs(ix.city.types.list) do
typeTbl[index] = type
end
local cityData = util.TableToJSON(cityTbl)
local typeData = util.TableToJSON(typeTbl)
net.Start("ix.city.RequestTypes")
net.WriteString(typeData)
net.Send(client)
net.Start("ix.city.PopulateFunds")
net.WriteString(cityData)
net.Send(client)
end)

View File

@@ -0,0 +1,118 @@
--[[
| 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 = "City Funds"
PLUGIN.author = "Naast"
PLUGIN.description = "Adds city funds. Yeah."
CAMI.RegisterPrivilege({
Name = "Helix - Manage City Fund",
MinAccess = "superadmin"
})
ix.util.IncludeDir(PLUGIN.folder .. "/meta", true)
ix.util.IncludeDir(PLUGIN.folder .. "/nets", true)
ix.util.Include("sv_plugin.lua")
ix.util.Include("sv_hooks.lua")
ix.util.Include("sv_stock_disallowments.lua")
ix.util.Include("sv_stock_restrictions.lua")
ix.config.Add("loanPercent", 2, "The amount of credits in percents that should be taken from city fund every day if it has a loan.", nil, {
data = {min = 0, max = 100},
category = "City Fund"
})
ix.config.Add("transactionVatPercent", 2, "The amount of credits in percents that should from player's transactions.", nil, {
data = {min = 0, max = 100},
category = "City Fund"
})
ix.config.Add("minusCityCap", 1000, "The maximum cap of negative balance of our city.", nil, {
data = {min = 0, max = 10000},
category = "City Fund"
})
ix.config.Add("mainCityNumber", 24, "Number of main (current playable) city.", nil, {
data = {min = 1, max = 99},
category = "City Fund"
})
ix.config.Add("averageItemProductionMaxRange", 15, "Max amount of average production items after rate time passes.", nil, {
data = {min = 10, max = 100},
category = "City Fund"
})
ix.config.Add("averageItemProductionMinRange", 5, "Min amount of average production items after rate time passes.", nil, {
data = {min = 1, max = 9},
category = "City Fund"
})
ix.config.Add("lowItemProductionMinRange", 5, "Min amount of low production items after rate time passes.", nil, {
data = {min = 1, max = 9},
category = "City Fund"
})
ix.config.Add("lowItemProductionMaxRange", 15, "Max amount of low production items after rate time passes.", nil, {
data = {min = 10, max = 100},
category = "City Fund"
})
ix.config.Add("highItemProductionMinRange", 5, "Min amount of high production items after rate time passes.", nil, {
data = {min = 1, max = 9},
category = "City Fund"
})
ix.config.Add("highItemProductionMaxRange", 15, "Max amount of high production items after rate time passes.", nil, {
data = {min = 10, max = 100},
category = "City Fund"
})
ix.config.Add("randItemDeletions", 3, "How much random item types (this can be one item multiple times) should be taken from every non-main city every hour.", nil, {
data = {min = 1, max = 100},
category = "City Fund"
})
ix.config.Add("randItemDeletionAmountRangeMin", 1, "Min range for taking one single item type from every non-main city every hour.", nil, {
data = {min = 1, max = 9},
category = "City Fund"
})
ix.config.Add("randItemDeletionAmountRangeMax", 15, "Min range for taking one single item type from every non-main city every hour.", nil, {
data = {min = 10, max = 100},
category = "City Fund"
})
ix.command.Add("CityFundEditor", {
description = "Manage and create cities.",
privilege = "Manage City Fund",
OnRun = function(self, client)
net.Start("ix.city.CreateCFEditor")
net.Send(client)
end
})
ix.command.Add("SimulateGOItime", {
description = "Updates city funds by forcing cities to handle their production functions.",
privilege = "Manage City Fund",
arguments = ix.type.number,
OnRun = function(self, client, time)
if time > 20 then return client:NotifyLocalized("Time is too high!") end
for i = 1, time do
ix.city:UpdateCityFunds()
end
end
})
if CLIENT then
ix.factionBudget:InitializeFactionBudgets()
end

View File

@@ -0,0 +1,24 @@
--[[
| 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/
--]]
function PLUGIN:SaveData()
if timer.Exists("ixCityFund") then
ix.data.Set("cityFundTimer", timer.TimeLeft("ixCityFund"))
end
ix.factionBudget:SaveBudgets()
end
function PLUGIN:LoadData()
ix.factionBudget:LoadBudgets()
end
function PLUGIN:InitPostEntity()
self:SetupProductionTimer()
end

View File

@@ -0,0 +1,72 @@
--[[
| 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/
--]]
function PLUGIN:DatabaseConnected()
local aQuery = mysql:Create("ix_citytypes")
aQuery:Create("t_id", "INT UNSIGNED NOT NULL AUTO_INCREMENT")
aQuery:Create("t_name", "TEXT")
aQuery:Create("t_data", "TEXT")
aQuery:PrimaryKey("t_id")
aQuery:Callback(function()
ix.city:LoadTypes()
end)
aQuery:Execute()
local nQuery = mysql:Create("ix_cities")
nQuery:Create("ct_id", "INT UNSIGNED NOT NULL")
nQuery:Create("ct_credits", "TEXT")
nQuery:Create("ct_type", "TEXT")
nQuery:Create("ct_items", "LONGTEXT")
nQuery:Create("ct_loan", "TEXT")
nQuery:Create("ct_loanRate", "TEXT")
nQuery:PrimaryKey("ct_id")
nQuery:Callback(function()
local fQuery = mysql:Select("ix_cities")
fQuery:Where("ct_id", "1")
fQuery:Callback(function(result)
if (!istable(result) or #result == 0) then
ix.city:InitializeMainCity()
return
end
ix.city:LoadCities()
end)
fQuery:Execute()
end)
nQuery:Execute()
end
function PLUGIN:SetupProductionTimer()
if timer.Exists("ixCityFund") then return end
timer.Create("ixCityFund", ix.data.Get("cityFundTimer", 3600), 0, function()
ix.city:UpdateCityFunds()
timer.Adjust("ixCityFund", 3600)
end)
end
ix.log.AddType("cityFundInteraction", function(client, operationType, creditAmount)
return string.format("[CITY FUND] %s has %s %s credits.", client:Name(), operationType, isstring(creditAmount) and creditAmount or tostring(creditAmount))
end)
ix.log.AddType("factionBudget", function(client, faction, from, to)
return string.format("[CITY FUND] %s has changed %s's budget from %s to %s credits.", client:Name(), faction, isstring(from) and from or tostring(from), isstring(to) and to or tostring(to))
end)
ix.log.AddType("factionBudgetCWU", function(client, operationType, creditAmount, faction)
return string.format("[CITY FUND] %s has %s %s credits from/in %s's budget.", client:Name(), operationType, isstring(creditAmount) and creditAmount or tostring(creditAmount), faction)
end)
ix.log.AddType("marketInteraction", function(client, interactionType, amount, item, credAmount)
return string.format("[CITY FUND] %s has %s %s item(s): %s for %s credits.", client:Name(), interactionType, isstring(amount) and amount or tostring(amount), item, isstring(credAmount) and credAmount or tostring(credAmount))
end)
ix.log.AddType("stockInteraction", function(client, item)
return string.format("[CITY FUND] %s took %s from city stock.", client:Name(), item)
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/
--]]
-- example: ix.city:AddDisallowment("comp_plastic")
ix.city:AddDisallowment("apartmentkey")
ix.city:AddDisallowment("shopkey")
ix.city:AddDisallowment("legs_black_padded_pants")
ix.city:AddDisallowment("legs_blue_padded_pants")
ix.city:AddDisallowment("legs_green_padded_pants")
ix.city:AddDisallowment("torso_green_rebel_uniform")
ix.city:AddDisallowment("torso_blue_rebel_uniform")
ix.city:AddDisallowment("torso_medical_rebel_uniform")
ix.city:AddDisallowment("torso_blue_kevlar")
ix.city:AddDisallowment("torso_green_kevlar")
ix.city:AddDisallowment("torso_green_kevlar_t3")
ix.city:AddDisallowment("torso_medical_kevlar")
ix.city:AddDisallowment("torso_green_kevlar_t2")
ix.city:AddDisallowment("combine_card")
ix.city:AddDisallowment("id_card")
ix.city:AddDisallowment("fake_id_card")
ix.city:AddDisallowment("dummy_smallbomb")
ix.city:AddDisallowment("dummy_mediumbomb")
ix.city:AddDisallowment("dummy_biolock_expar2")
ix.city:AddDisallowment("dummy_biolock_ar2")
ix.city:AddDisallowment("dummy_biolock_ociw")
ix.city:AddDisallowment("dummy_biolock_sr1")
ix.city:AddDisallowment("dummy_emp")
ix.city:AddDisallowment("dummy_largebomb")
ix.city:AddDisallowment("dummy_littlebomb")
ix.city:AddDisallowment("funnybugbait")
ix.city:AddDisallowment("trash_biolock")
ix.city:AddDisallowment("cmbkey")
ix.city:AddDisallowment("militarykey")
ix.city:AddDisallowment("customitem_m")
ix.city:AddDisallowment("customitem_s")
ix.city:AddDisallowment("customitem_l")
ix.city:AddDisallowment("customitem_xl")
ix.city:AddDisallowment("itemlabel")
ix.city:AddDisallowment("vendingmachinekey")
ix.city:AddDisallowment("fake_id_card_creator")
ix.city:AddDisallowment("shackleskey")
ix.city:AddDisallowment("newspaper_printer_cracked")
ix.city:AddDisallowment("ing_xen_extract")
ix.city:AddDisallowment("ic_cluster_hive")
ix.city:AddDisallowment("ic_coarctate_mucus")
ix.city:AddDisallowment("ic_thanarok_embryo")
ix.city:AddDisallowment("ic_thanatos_embryo")
ix.city:AddDisallowment("ic_nosos_heart")
ix.city:AddDisallowment("tool_chembench")
ix.city:AddDisallowment("tool_metalbench")
ix.city:AddDisallowment("tool_oven")
ix.city:AddDisallowment("tool_oven_rusty")
ix.city:AddDisallowment("tool_mixer")
ix.city:AddDisallowment("tool_creammachine")
ix.city:AddDisallowment("tool_craftingbench")

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/
--]]
-- example: ix.city:AddCombineRestriction("akm")
-- also, you are able to restrict the whole item category just like this: ix.city:AddCombineRestriction("Weapons")
ix.city:AddCombineRestriction("Weapons")
ix.city:AddCombineRestriction("Combine")
ix.city:AddCombineRestriction("Clothing - CCA")
ix.city:AddCombineRestriction("manhack")
ix.city:AddCombineRestriction("health_syringe")
ix.city:AddCombineRestriction("turret_placer")
ix.city:AddCombineRestriction("barricade_placer")
ix.city:AddCombineRestriction("tool_repair")
ix.city:AddCombineRestriction("Ammunition (New)")
ix.city:AddCombineRestriction("Ammunition")
ix.city:AddCombineRestriction("Combine")
ix.city:AddCombineRestriction("Attachments")
ix.city:AddCombineRestriction("Attachments (ArcCW)")
ix.city:AddCombineRestriction("Clothing - Collaborator")
ix.city:AddCombineRestriction("Loyalism")
ix.city:AddCombineRestriction("Xen")
ix.city:AddCombineRestriction("landline")
ix.city:AddCombineRestriction("tuner_cmb")
ix.city:AddCombineRestriction("tuner_reb")
ix.city:AddCombineRestriction("armband_green")
ix.city:AddCombineRestriction("armband_black")
ix.city:AddCombineRestriction("armband_blue")
ix.city:AddCombineRestriction("armband_icobt")
ix.city:AddCombineRestriction("armband_grey")
ix.city:AddCombineRestriction("armband_orange")
ix.city:AddCombineRestriction("armband_purple")
ix.city:AddCombineRestriction("armband_red")
ix.city:AddCombineRestriction("armband_white")
ix.city:AddCombineRestriction("armband_whitestar")
ix.city:AddCombineRestriction("armband_yellow")
ix.city:AddCombineRestriction("wn_zip_tie")