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,108 @@
--[[
| 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 smallerIconSize = SScaleMin(16 / 3)
local function firstUpper(str)
return str:gsub("^%l", string.utf8upper)
end
function PLUGIN:PopulateHelpMenu(tabs)
local permitsList = ix.permits.get()
if (permitsList and !table.IsEmpty(permitsList)) then
tabs["Permits"] = function(container)
local permits = table.GetKeys(permitsList)
table.sort(permits)
for _, v in pairs(permits) do
local permitsButton = container:Add("DButton")
permitsButton:Dock(TOP)
permitsButton:SetText(Schema:FirstToUpper(v))
permitsButton:SetFont("TitlesFontNoClamp")
permitsButton:SizeToContents()
permitsButton.Paint = nil
permitsButton:SetContentAlignment(4)
permitsButton.DoClick = function()
LocalPlayer():NotifyLocalized("Permit ID '"..v.."' copied to clipboard")
SetClipboardText( v )
end
end
end
end
end
function PLUGIN:CreateExtraCharacterTabInfo(character, informationSubframe, CreatePart)
-- Permits
local permitsPanel = informationSubframe:Add("Panel")
local permitsData = LocalPlayer():GetCharacter():GetGenericdata().permits
if !istable(permitsData) then
CreatePart(permitsPanel, "Business Permits:", "No permits", "licenses", true, false, true)
return
end
permitsData = table.GetKeys(LocalPlayer():GetCharacter():GetGenericdata().permits)
for k, v in pairs(permitsData) do
permitsData[k] = firstUpper(v)
end
if !table.IsEmpty(permitsData) then
CreatePart(permitsPanel, "Business Permits:", table.concat(permitsData, ", "), "licenses", true, false, true)
else
CreatePart(permitsPanel, "Business Permits:", "No permits", "licenses", true, false, true)
end
end
function PLUGIN:AdjustInnerStatusPanel(innerStatus, CreateTitle, CreateSubBar)
if (ix.special) then
local attributesTitle = innerStatus:Add("DLabel")
CreateTitle(attributesTitle, "ATTRIBUTES")
local character = LocalPlayer():GetCharacter()
for _, v in pairs(ix.special.list) do
local attribute = innerStatus:Add("Panel")
local special = character:GetSpecial(tostring(v.uniqueID))
CreateSubBar(attribute, "willardnetworks/tabmenu/inventory/inv_" .. v.name .. ".png", v.name, special .. "/10", smallerIconSize, smallerIconSize)
end
end
if (ix.skill) then
local character = LocalPlayer():GetCharacter()
local skillsTitle = innerStatus:Add("DLabel")
CreateTitle(skillsTitle, "SKILLS")
for skillID, skillInfo in pairs(ix.skill.list) do
if (skillInfo.name == "Vortessence" and !LocalPlayer():IsVortigaunt()) or skillInfo.name == "Bartering" then
continue
end
local skillsPanel = innerStatus:Add("Panel")
local level = character:GetSkillLevel(skillID)
CreateSubBar(skillsPanel, "willardnetworks/tabmenu/inventory/inv_" .. skillID .. ".png", skillInfo.name, level .. "/50", smallerIconSize, smallerIconSize)
end
local char = LocalPlayer().GetCharacter and LocalPlayer():GetCharacter()
-- Misc section
local miscTitle = innerStatus:Add("DLabel")
CreateTitle(miscTitle, "MISC")
if char then
local money = char.GetMoney and char:GetMoney() or 0
-- Display the amount of chips the player has
local chipsPanel = innerStatus:Add("Panel")
CreateSubBar(chipsPanel, "willardnetworks/tabmenu/charmenu/chips.png", "Chips", money, smallerIconSize, smallerIconSize)
end
end
end

View File

@@ -0,0 +1,33 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLUGIN = PLUGIN
netstream.Hook("RebuildCrafting", function(data)
PLUGIN.craftingPanel:Rebuild()
end)
netstream.Hook("CraftTime", function(data)
ix.CraftCooldown = data
end)
netstream.Hook("SendMessageListToClient", function(messagelist, storedNewspapers)
LocalPlayer().messagelist = messagelist
local capda = vgui.Create("ixCAPDA")
capda.storedNewspapers = storedNewspapers
capda:CreateNewspaperButton()
end)
-- Called when the local player's crafting is rebuilt.
function PLUGIN:PlayerCraftingRebuilt(panel, categories) end
-- Called when the local player's crafting item should be adjusted.
function PLUGIN:PlayerAdjustCraftingRecipe(recipe) end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,493 @@
--[[
| 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 padding = SScaleMin(10 / 3)
function PANEL:Init()
self:SetSize(ScrW(), ScrH())
self:SetAlpha(0)
self:AlphaTo(255, 0.5, 0)
self.Paint = function( self, w, h )
surface.SetDrawColor(Color(63, 58, 115, 220))
surface.DrawRect(0, 0, w, h)
Derma_DrawBackgroundBlur( self, 1 )
end
self.content = self:Add("EditablePanel")
self.content:SetSize(SScaleMin(400 / 3), SScaleMin(600 / 3))
self.content:Center()
self.content:MakePopup()
Schema:AllowMessage(self.content)
self.content.Paint = function(self, w, h)
surface.SetDrawColor(0, 0, 0, 130)
surface.DrawRect(0, 0, w, h)
end
self.topbar = self.content:Add("Panel")
self.topbar:SetSize(self.content:GetWide(), SScaleMin(50 / 3))
self.topbar:Dock(TOP)
self.topbar.Paint = function( self, w, h )
surface.SetDrawColor(0, 0, 0, 130)
surface.DrawRect(0, 0, w, h)
end
local titleText = self.topbar:Add("DLabel")
titleText:SetFont("LargerTitlesFontNoClamp")
titleText:Dock(LEFT)
titleText:SetText("Civil Administration")
titleText:DockMargin(SScaleMin(10 / 3), 0, 0, 0)
titleText:SetContentAlignment(4)
titleText:SizeToContents()
local exit = self.topbar:Add("DImageButton")
exit:SetImage("willardnetworks/tabmenu/navicons/exit.png")
exit:SetSize(SScaleMin(20 / 3), SScaleMin(20 / 3))
exit:DockMargin(0, SScaleMin(15 / 3), SScaleMin(10 / 3), SScaleMin(15 / 3))
exit:Dock(RIGHT)
exit.DoClick = function()
LocalPlayer().messagelist = nil
self:Remove()
surface.PlaySound("helix/ui/press.wav")
end
self:CreateInner()
end
local function PaintButton(self, w, h)
surface.SetDrawColor(Color(0, 0, 0, 100))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
surface.DrawOutlinedRect(0, 0, w, h)
end
function PANEL:CreateBackButton()
local divider = self.topbar:Add("DShape")
divider:SetType("Rect")
divider:Dock(RIGHT)
divider:DockMargin(padding, padding, padding, padding)
divider:SetWide(1)
divider:SetColor(Color(111, 111, 136, (255 / 100 * 30)))
local back = self.topbar:Add("DButton")
back:Dock(RIGHT)
back:SetText("BACK")
back:SetFont("TitlesFontNoClamp")
back.Paint = nil
back:SizeToContents()
back.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
self:Remove()
local panel = vgui.Create("ixCAPDA")
panel:SetAlpha(255)
end
end
function PANEL:CreateNewspaperButton()
self.newspapers = self.innerContent:Add("DButton")
self.newspapers:Dock(TOP)
self.newspapers:SetTall(SScaleMin(50 / 3))
self.newspapers:SetText("Union Newspapers")
self.newspapers:SetFont("WNBleedingMinutesBoldNoClamp")
self.newspapers:SetContentAlignment(4)
self.newspapers:SetTextInset(SScaleMin(10 / 3), 0)
self.newspapers.Paint = function(self, w, h)
PaintButton(self, w, h)
end
self.newspapers:DockMargin(0, -1, 0, 0)
self.newspapers.DoClick = function()
self:CreateBackButton()
surface.PlaySound("helix/ui/press.wav")
self.innerContent:Clear()
for k, v in pairs(self.storedNewspapers) do
local newspaper = self.innerContent:Add("DButton")
newspaper:Dock(TOP)
newspaper:SetTall(SScaleMin(50 / 3))
newspaper:SetText(v[3][1].columnTitle.." | "..v[3][1].columnSubtitle)
newspaper:SetFont("WNBleedingMinutesBoldNoClamp")
newspaper:SetContentAlignment(4)
newspaper:SetTextInset(SScaleMin(10 / 3), 0)
newspaper.Paint = function(self, w, h)
PaintButton(self, w, h)
end
if k != 1 then
newspaper:DockMargin(0, -1, 0, 0)
end
newspaper.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
local areyousure = vgui.Create("Panel")
areyousure:SetSize(SScaleMin(300 / 3), SScaleMin(100 / 3))
areyousure:Center()
areyousure:MakePopup()
areyousure.Paint = function(self, w, h)
PaintButton(self, w, h)
end
local label = areyousure:Add("DLabel")
label:SetFont("WNBleedingMinutesBoldNoClamp")
label:SetText("Remove stored newspaper?")
label:SizeToContents()
label:Dock(TOP)
label:SetContentAlignment(5)
local buttonpanel = areyousure:Add("Panel")
buttonpanel:Dock(BOTTOM)
buttonpanel:SetTall(SScaleMin(50 / 3))
local yes = buttonpanel:Add("DButton")
yes:Dock(LEFT)
yes:SetWide((areyousure:GetWide() * 0.5) - SScaleMin(5 / 3))
yes:SetText("Yes")
yes:SetFont("MenuFontNoClamp")
yes.Paint = function(self, w, h)
PaintButton(self, w, h)
end
yes.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
areyousure:Remove()
newspaper:Remove()
netstream.Start("RemoveStoredNewspaper", k)
end
local no = buttonpanel:Add("DButton")
no:Dock(RIGHT)
no:SetWide((areyousure:GetWide() * 0.5) - SScaleMin(5 / 3))
no:SetText("No")
no:SetFont("MenuFontNoClamp")
no.Paint = function(self, w, h)
PaintButton(self, w, h)
end
no.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
areyousure:Remove()
end
end
end
end
end
function PANEL:CreateDoorAccessButton()
self.doorAccess = self.innerContent:Add("DButton")
self.doorAccess:Dock(TOP)
self.doorAccess:SetTall(SScaleMin(50 / 3))
self.doorAccess:SetText("Combine Doors")
self.doorAccess:SetFont("WNBleedingMinutesBoldNoClamp")
self.doorAccess:SetContentAlignment(4)
self.doorAccess:SetTextInset(SScaleMin(10 / 3), 0)
self.doorAccess.Paint = function(self, w, h)
PaintButton(self, w, h)
end
self.doorAccess:DockMargin(0, -1, 0, 0)
self.doorAccess.DoClick = function()
self:CreateBackButton()
surface.PlaySound("helix/ui/press.wav")
self.innerContent:Clear()
for k, v in ipairs(ents.GetAll()) do
if (v:IsDoor()) then
if (!v:HasSpawnFlags(256) and !v:HasSpawnFlags(1024) and v:GetNetVar("combineDoor")) then
local name = v:GetNetVar("combineDoor")
if name then
local doorNameButton = self.innerContent:Add("DButton")
doorNameButton:Dock(TOP)
doorNameButton:SetText(name)
doorNameButton:SetTall(SScaleMin(50 / 3))
doorNameButton:SetFont("WNBleedingMinutesBoldNoClamp")
doorNameButton:SetContentAlignment(4)
doorNameButton:SetTextInset(padding, 0)
doorNameButton.Paint = function(self, w, h)
PaintButton(self, w, h)
end
doorNameButton.DoClick = function()
Derma_StringRequest(
"Grant Access",
"Enter CID",
"",
function(enteredCid)
for k2, v2 in pairs(ix.char.loaded) do
if v2:GetCid() == enteredCid then
netstream.Start("SetDoorAccessCID", v, k2)
break
end
end
end,
nil
)
end
end
end
end
end
end
end
function PANEL:CreateInner()
self.innerContent = self.content:Add("DScrollPanel")
self.innerContent:Dock(TOP)
self.innerContent:SetTall(self.content:GetTall() - SScaleMin(50 / 3))
self.barteringConfigs = self.innerContent:Add("DButton")
self.barteringConfigs:Dock(TOP)
self.barteringConfigs:SetTall(SScaleMin(50 / 3))
self.barteringConfigs:SetText("Bartering")
self.barteringConfigs:SetFont("WNBleedingMinutesBoldNoClamp")
self.barteringConfigs:SetContentAlignment(4)
self.barteringConfigs:SetTextInset(padding, 0)
self.barteringConfigs.Paint = function(self, w, h)
PaintButton(self, w, h)
end
self.barteringConfigs.DoClick = function()
self:CreateBackButton()
surface.PlaySound("helix/ui/press.wav")
self.innerContent:Clear()
local recipes = ix.recipe.stored
local categories = {}
for uniqueID, RECIPE in SortedPairs(recipes) do
if RECIPE.cost and RECIPE.skill == "bartering" then
if !table.HasValue(categories, RECIPE.category) then
table.insert(categories, RECIPE.category)
local priceMultiplier = self.innerContent:Add("DButton")
priceMultiplier:Dock(TOP)
priceMultiplier:SetText("Price Multiplier "..RECIPE.category)
priceMultiplier:SetTall(SScaleMin(50 / 3))
priceMultiplier:SetFont("WNBleedingMinutesBoldNoClamp")
priceMultiplier:SetContentAlignment(4)
priceMultiplier:SetTextInset(padding, 0)
priceMultiplier.Paint = function(self, w, h)
PaintButton(self, w, h)
end
priceMultiplier.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
Derma_StringRequest(
"Set Multiplier "..RECIPE.category,
"Price multiplier "..RECIPE.category.." (1 decimal max, default is 1.0)",
ix.config.Get("BarteringPriceMultiplier"..RECIPE.category),
function(number)
local toNumber = tonumber(number)
if isnumber(toNumber) then
local maxValue = ix.config.stored.BarteringPriceMultiplierClothing.data.data.max or 100
local minValue = ix.config.stored.BarteringPriceMultiplierClothing.data.data.min or 0
if (toNumber <= maxValue) and (toNumber >= minValue) then
netstream.Start("ixBarteringPriceMultiplier", RECIPE.category, tonumber(number))
LocalPlayer():NotifyLocalized("Set Bartering Price Multiplier "..RECIPE.category.." to "..number)
else
LocalPlayer():NotifyLocalized("Number needs to be below or equal to 100 and above or equal to 0")
end
end
end,
nil
)
end
end
end
end
end
self.ration = self.innerContent:Add("DButton")
self.ration:Dock(TOP)
self.ration:SetTall(SScaleMin(50 / 3))
self.ration:SetText("Rations")
self.ration:SetFont("WNBleedingMinutesBoldNoClamp")
self.ration:SetContentAlignment(4)
self.ration:SetTextInset(padding, 0)
self.ration.Paint = function(self, w, h)
PaintButton(self, w, h)
end
self.ration:DockMargin(0, -1, 0, 0)
self.ration.DoClick = function()
self:CreateBackButton()
surface.PlaySound("helix/ui/press.wav")
self.innerContent:Clear()
local rationInterval = self.innerContent:Add("DButton")
rationInterval:Dock(TOP)
rationInterval:SetTall(SScaleMin(50 / 3))
rationInterval:SetText("Ration Interval")
rationInterval:SetFont("WNBleedingMinutesBoldNoClamp")
rationInterval:SetContentAlignment(4)
rationInterval:SetTextInset(padding, 0)
rationInterval.Paint = function(self, w, h)
PaintButton(self, w, h)
end
rationInterval.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
Derma_StringRequest(
"Set Ration Interval",
"Set Ration Interval in hours (0 decimals, default is 4)",
ix.config.Get("rationInterval"),
function(number)
local toNumber = tonumber(number)
if isnumber(toNumber) then
local maxValue = ix.config.stored.rationInterval.data.data.max or 10
local minValue = ix.config.stored.rationInterval.data.data.min or 1
if (toNumber <= maxValue) and (toNumber >= minValue) then
netstream.Start("SetRationIntervalPDA", tonumber(number))
LocalPlayer():NotifyLocalized("Set Ration Interval timer to "..number.. " hours")
else
LocalPlayer():NotifyLocalized("Number needs to be below or equal to 10 and above or equal to 1")
end
end
end,
nil)
end
end
if istable(LocalPlayer().messagelist) then
if !table.IsEmpty(LocalPlayer().messagelist) then
self.messages = self.innerContent:Add("DButton")
self.messages:Dock(TOP)
self.messages:SetTall(SScaleMin(50 / 3))
self.messages:SetText("Messages")
self.messages:SetFont("WNBleedingMinutesBoldNoClamp")
self.messages:SetContentAlignment(4)
self.messages:SetTextInset(padding, 0)
self.messages.Paint = function(self, w, h)
PaintButton(self, w, h)
end
self.messages:DockMargin(0, -1, 0, 0)
self.messages.DoClick = function()
self:CreateBackButton()
surface.PlaySound("helix/ui/press.wav")
self.innerContent:Clear()
local messagePanel = self.innerContent:Add("Panel")
messagePanel:Dock(TOP)
messagePanel:SetTall(self.innerContent:GetTall())
for k, v in pairs(LocalPlayer().messagelist) do
local message = messagePanel:Add("DButton")
message:Dock(TOP)
message:SetTall(SScaleMin(50 / 3))
message:SetText(v["message_date"].." | "..string.utf8sub(v["message_poster"], 1, 18).." | #"..v["message_cid"])
if v["message_reply"] then
message:SetTextColor(Color(210, 255, 255, 255))
else
message:SetTextColor(Color(255, 205, 205, 255))
end
message:SetFont("WNBleedingMinutesBold")
message:SetContentAlignment(4)
message:SetTextInset(padding, 0)
message.Paint = function(self, w, h)
PaintButton(self, w, h)
end
if k != 1 then
message:DockMargin(0, -1, 0, 0)
end
message.DoClick = function()
messagePanel:Clear()
surface.PlaySound("helix/ui/press.wav")
local textEntry = messagePanel:Add("DTextEntry")
textEntry:Dock(FILL)
textEntry:SetTextColor(Color(200, 200, 200, 255))
textEntry:SetMultiline( true )
textEntry:SetEditable(false)
textEntry:SetVerticalScrollbarEnabled( true )
textEntry:SetCursorColor(Color(200, 200, 200, 255))
textEntry:SetValue(v["message_text"])
textEntry.Paint = function(self, w, h)
surface.SetDrawColor(Color(0, 0, 0, 100))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
surface.DrawOutlinedRect(0, 0, w, h)
self:DrawTextEntryText( self:GetTextColor(), self:GetHighlightColor(), self:GetCursorColor() )
end
local optionsPanel = messagePanel:Add("Panel")
optionsPanel:Dock(BOTTOM)
optionsPanel:SetSize(self.content:GetWide(), SScaleMin(50 / 3))
local remove = optionsPanel:Add("DButton")
remove:Dock(FILL)
remove:SetText("REMOVE")
remove:SetFont("WNBleedingMinutesBoldNoClamp")
remove:SetContentAlignment(5)
remove.Paint = function(self, w, h)
PaintButton(self, w, h)
end
remove.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
LocalPlayer().messagelist[k] = nil
netstream.Start("RemoveCAMessage", v["message_id"])
self.innerContent:Remove()
self:CreateInner()
end
local sendReply = optionsPanel:Add("DButton")
sendReply:Dock(RIGHT)
sendReply:SetWide(optionsPanel:GetWide() * 0.5)
if v["message_reply"] then
sendReply:SetText("READ REPLY")
else
sendReply:SetText("REPLY")
end
sendReply:SetFont("WNBleedingMinutesBold")
sendReply:SetContentAlignment(5)
sendReply.Paint = function(self, w, h)
PaintButton(self, w, h)
end
sendReply.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
if v["message_reply"] then
textEntry:SetValue(v["message_reply"])
return
end
textEntry:SetEditable(true)
sendReply:SetText("SEND REPLY")
textEntry:SetValue("Write your reply here..")
sendReply.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
v["message_reply"] = textEntry:GetValue()
netstream.Start("SetCAMessageReply", v["message_id"], textEntry:GetValue())
self.innerContent:Remove()
self:CreateInner()
end
end
end
end
end
end
end
self:CreateDoorAccessButton()
end
vgui.Register("ixCAPDA", PANEL, "EditablePanel")

View File

@@ -0,0 +1,224 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PANEL = {}
function PANEL:Init()
self:SetSize(ScrW(), ScrH())
self:SetAlpha(0)
self:AlphaTo(255, 0.5, 0)
self.Paint = function(this, w, h)
surface.SetDrawColor(Color(63, 58, 115, 220))
surface.DrawRect(0, 0, w, h)
Derma_DrawBackgroundBlur( this, 1 )
end
self.innerContent = self:Add("Panel")
self.innerContent:SetSize(SScaleMin(500 / 3), SScaleMin(600 / 3))
self.innerContent:Center()
self.innerContent:MakePopup()
Schema:AllowMessage(self.innerContent)
self.innerContent.Paint = function(this, w, h)
surface.SetDrawColor(0, 0, 0, 130)
surface.DrawRect(0, 0, w, h)
end
self:CreateTopBar()
self:CreateItems()
end
function PANEL:CreateTopBar()
local topbar = self.innerContent:Add("Panel")
topbar:SetSize(self.innerContent:GetWide(), SScaleMin(50 / 3))
topbar:Dock(TOP)
topbar.Paint = function( this, w, h )
surface.SetDrawColor(0, 0, 0, 130)
surface.DrawRect(0, 0, w, h)
end
self.titleText = topbar:Add("DLabel")
self.titleText:SetFont("CharCreationBoldTitleNoClamp")
self.titleText:Dock(LEFT)
self.titleText:SetText("Select item to dispense")
self.titleText:DockMargin(SScaleMin(10 / 3), 0, 0, 0)
self.titleText:SetContentAlignment(4)
self.titleText:SizeToContents()
self.exit = topbar:Add("DImageButton")
self.exit:SetImage("willardnetworks/tabmenu/navicons/exit.png")
self.exit:SetSize(SScaleMin(20 / 3), SScaleMin(20 / 3))
self.exit:DockMargin(0, SScaleMin(15 / 3), SScaleMin(10 / 3), SScaleMin(15 / 3))
self.exit:Dock(RIGHT)
self.exit.DoClick = function()
netstream.Start("ClosePanels", LocalPlayer().activePickupDispenser)
LocalPlayer().activePickupDispenser = nil
LocalPlayer().boughtItems = nil
self:Remove()
surface.PlaySound("helix/ui/press.wav")
end
local function createDivider(parent)
parent:SetSize(1, topbar:GetTall())
parent:Dock(RIGHT)
parent:DockMargin(0, SScaleMin(10 / 3), SScaleMin(SScaleMin(10 / 3) / 3), SScaleMin(10 / 3))
parent.Paint = function(this, w, h)
surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
surface.DrawLine(0, 0, 0, h)
end
end
local divider = topbar:Add("Panel")
createDivider(divider)
end
function PANEL:CreateItems()
if !LocalPlayer().boughtItems then
return
end
local scrollPanel = self.innerContent:Add("DScrollPanel")
scrollPanel:Dock(TOP)
scrollPanel:SetSize(self.innerContent:GetWide(), self.innerContent:GetTall() - SScaleMin(50 / 3))
for k, v in pairs (LocalPlayer().boughtItems) do
local character = LocalPlayer():GetCharacter()
local inventory = character:GetInventory()
local width = istable(v) and 1 or ix.item.list[k].width or 1
local height = istable(v) and 1 or ix.item.list[k].height or 1
local frame, modelPanel, textPanel, amountPanel, amount, title = self:CreateItem(scrollPanel, k, v)
local actualAmount = istable(v) and 1 or v or 1
local actualTitle = istable(v) and v.title or ix.item.list[k].name or "Cardboard Box"
if !inventory:FindEmptySlot(width, height) then
amount:SetTextColor(Color(150, 150, 150, 255))
title:SetTextColor(Color(150, 150, 150, 255))
end
self:CreateInvisibleButton(frame, modelPanel, textPanel, amountPanel, inventory, width, height, actualAmount, actualTitle, amount, k)
end
end
function PANEL:CreateInvisibleButton(frame, modelPanel, textPanel, amountPanel, inventory, width, height, actualAmount, actualTitle, amount, k)
local invisibleButton = frame:Add("DButton")
invisibleButton:SetSize(modelPanel:GetWide() + textPanel:GetWide() + amountPanel:GetWide(), frame:GetTall())
invisibleButton:SetText("")
invisibleButton.Paint = function(this, w, h)
if inventory then
if (this:IsHovered() and !inventory:FindEmptySlot(width, height)) then
surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 15)))
surface.DrawOutlinedRect(SScaleMin(4 / 3), SScaleMin(4 / 3), w - SScaleMin(8 / 3), h - SScaleMin(8 / 3))
end
return
end
if (this:IsHovered()) then
surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 15)))
surface.DrawOutlinedRect(SScaleMin(4 / 3), SScaleMin(4 / 3), w - SScaleMin(8 / 3), h - SScaleMin(8 / 3))
end
end
invisibleButton.DoClick = function()
if inventory then
if inventory:FindEmptySlot(width, height) then
actualAmount = actualAmount - 1
amount:SetText(actualAmount)
if actualAmount == 0 then
frame:Remove()
end
LocalPlayer():NotifyLocalized("You have picked up a "..actualTitle)
surface.PlaySound("helix/ui/press.wav")
netstream.Start("SetPurchasedItems", k, LocalPlayer().activePickupDispenser)
else
LocalPlayer():NotifyLocalized("You do not have enough space for "..actualTitle.."!")
end
end
end
return invisibleButton
end
function PANEL:CreateItem(scrollPanel, itemID, number)
local frame = scrollPanel:Add("Panel")
frame:Dock(TOP)
frame:DockMargin(0, 0, 0, -1)
frame:SetTall(SScaleMin(110 / 3) - 5)
frame.Paint = function(this, w, h)
surface.SetDrawColor(Color(0, 0, 0, 100))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
surface.DrawOutlinedRect(0, 0, w, h)
end
local modelPanel = frame:Add("Panel")
modelPanel:Dock(LEFT)
modelPanel:SetWide(scrollPanel:GetWide() / 3)
modelPanel.Paint = function(this, w, h)
surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
surface.DrawLine(w - 1, SScaleMin(10 / 3), w - 1, h - SScaleMin(10 / 3))
end
local modelIcon = modelPanel:Add("SpawnIcon")
local model = istable(number) and "models/props_c17/paper01.mdl" or ix.item.list[itemID].model or "models/props_junk/cardboard_box004a.mdl"
modelIcon:Dock(FILL)
modelIcon:DockMargin(SScaleMin(43 / 3), SScaleMin(10 / 3), SScaleMin(43 / 3), SScaleMin(10 / 3))
modelIcon:SetModel(model)
modelIcon.Paint = nil
modelIcon.PaintOver = nil
modelIcon:SetTooltip(nil)
local textPanel = frame:Add("Panel")
textPanel:Dock(LEFT)
textPanel:DockPadding(SScaleMin(10 / 3), 0, SScaleMin(10 / 3), 0)
textPanel:SetSize(scrollPanel:GetWide() / 2, frame:GetTall())
textPanel.Paint = function(this, w, h)
surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
surface.DrawLine(w - 1, SScaleMin(10 / 3), w - 1, h - SScaleMin(10 / 3))
end
local title = textPanel:Add("DLabel")
local actualTitle = istable(number) and number.title or ix.item.list[itemID].name or "Cardboard Box"
title:Dock(TOP)
title:SetText(actualTitle..(istable(number) and " - FROM: "..number.fromName.." | "..number.fromCID or ""))
title:SetFont(istable(number) and "MenuFontBoldNoClamp" or "WNBleedingMinutesBoldNoClamp")
title:SetWrap(true)
title:SetAutoStretchVertical(true)
title.PerformLayout = function(this)
this:DockMargin(0, textPanel:GetTall() * 0.5 - this:GetTall() * 0.5, 0, textPanel:GetTall() * 0.5 - this:GetTall() * 0.5)
end
local amountPanel = frame:Add("Panel")
amountPanel:Dock(FILL)
amountPanel:SetSize(scrollPanel:GetWide() - modelPanel:GetWide() - textPanel:GetWide(), frame:GetTall())
if LocalPlayer().boughtItems and istable(LocalPlayer().boughtItems) then
if table.Count(LocalPlayer().boughtItems) >= 6 then
amountPanel:SetWide(amountPanel:GetWide() - SScaleMin(15 / 3))
end
end
local amount = amountPanel:Add("DLabel")
local actualAmount = istable(number) and 1 or number or 1
amount:SetContentAlignment(5)
amount:SetText(actualAmount)
amount:SetFont("WNBleedingMinutesBoldNoClamp")
amount:SizeToContents()
amount:Center()
return frame, modelPanel, textPanel, amountPanel, amount, title
end
vgui.Register("PickupDispenser", PANEL, "EditablePanel")

View File

@@ -0,0 +1,63 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local vgui = vgui
local PANEL = {}
function PANEL:Init()
local parent = self:GetParent():GetParent()
self:SetSize(parent.contentPanel:GetSize())
-- Config
self.firstTitle = "Shipments"
self.secondTitle = "Purchase"
self.thirdTitle = "Preview"
self.nothingSelected = "No item selected"
self.requirementsTitleText = "Requirements: "
self.skill = "bartering"
self.built = false
ix.city:SyncCityStock()
end
function PANEL:Proceed()
self.built = true
-- Create titles
self:Add("CraftingBaseTopTitleBase")
-- Create inner content
self:Add("CraftingBaseInnerContent")
-- Rebuild inner content
self:Add("CraftingBaseRebuild")
end
function PANEL:Remove()
if (self.model) then
self.model:Remove()
end
end
vgui.Register("BarteringBasePanel", PANEL, "EditablePanel")
local function CreateBarteringPanel(container)
local panel = container:Add("BarteringBasePanel")
ix.gui.barteringpanel = panel
ix.gui.activeSkill = panel
return container
end
hook.Add("CreateSkillPanels", "BarteringBasePanel", function(tabs)
tabs[ix.skill.list["bartering"].uniqueID] = CreateBarteringPanel
end)

View File

@@ -0,0 +1,58 @@
--[[
| 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 vgui = vgui
local PANEL = {}
function PANEL:Init()
local parent = self:GetParent():GetParent()
self:SetSize(parent.contentPanel:GetSize())
-- Config
self.firstTitle = "Recipes"
self.secondTitle = "Cook"
self.thirdTitle = "Preview"
self.nothingSelected = "No item selected"
self.requirementsTitleText = "Requirements: "
self.ingredientsTitleText = "Ingredients:"
self.skill = "cooking"
self.craftSound = "willardnetworks/skills/skill_cooking.wav"
-- Create titles
self:Add("CraftingBaseTopTitleBase")
-- Create inner content
self:Add("CraftingBaseInnerContent")
-- Rebuild inner content
self:Add("CraftingBaseRebuild")
end
function PANEL:Remove()
if (self.model) then
self.model:Remove()
end
end
vgui.Register("CookingBasePanel", PANEL, "EditablePanel")
local function CreateCookingPanel(container)
local panel = container:Add("CookingBasePanel")
ix.gui.cookingpanel = panel
ix.gui.activeSkill = panel
return container
end
hook.Add("CreateSkillPanels", "CookingBasePanel", function(tabs)
tabs[ix.skill.list["cooking"].uniqueID] = CreateCookingPanel
end)

View File

@@ -0,0 +1,102 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local vgui = vgui
local PANEL = {}
function PANEL:Init()
local parent = self:GetParent():GetParent()
if parent then
if parent.contentPanel then
self:SetSize(parent.contentPanel:GetSize())
else
self:SetSize(ScrW() * 0.75, ScrH() * 0.70)
end
else
self:SetSize(ScrW() * 0.75, ScrH() * 0.70)
end
-- Config
self.firstTitle = "Recipes"
self.secondTitle = "Crafting"
self.thirdTitle = "Preview"
self.nothingSelected = "No item/recipe selected"
self.requirementsTitleText = "Requirements: "
self.ingredientsTitleText = "Ingredients:"
self.skill = "crafting"
self.craftSound = "willardnetworks/skills/skill_crafting.wav"
-- Create titles
self:Add("CraftingBaseTopTitleBase")
-- Create inner content
self:Add("CraftingBaseInnerContent")
-- Rebuild inner content
self:Add("CraftingBaseRebuild")
end
function PANEL:Remove()
if (self.model) then
self.model:Remove()
end
end
vgui.Register("CraftingBasePanel", PANEL, "EditablePanel")
local function CreateCraftingPanel(container)
local panel = container:Add("CraftingBasePanel")
ix.gui.craftingpanel = panel
ix.gui.activeSkill = panel
return container
end
hook.Add("CreateSkillPanels", "CraftingBasePanel", function(tabs)
tabs[ix.skill.list["crafting"].uniqueID] = CreateCraftingPanel
end)
netstream.Hook("OpenCraftingMenu", function()
if ix.gui.craftingpanel then
if ix.gui.craftingpanel.Remove then
ix.gui.craftingpanel:Remove()
end
end
local parentPanel = vgui.Create("Panel")
parentPanel:SetSize(ScrW(), ScrH())
parentPanel:SetAlpha(0)
parentPanel:AlphaTo(200, 0.5, 0)
parentPanel.Paint = function(self, w, h)
surface.SetDrawColor(0, 0, 0, 255)
surface.DrawRect(0, 0, w, h)
end
local craftingPanel = parentPanel:Add("CraftingBasePanel")
craftingPanel:MakePopup()
craftingPanel:Center()
local close = craftingPanel:Add("DButton")
close:Dock(BOTTOM)
close:SetFont("TitlesFont")
close:SetText("CLOSE CRAFTING")
close:DockMargin(((craftingPanel:GetWide() + 20) / 1.5), 0, 2, 0)
close:SetTall(math.Clamp(ScreenScale(50 / 3), 0, 50))
close.DoClick = function()
parentPanel:AlphaTo(0, 0.5, 0, function()
parentPanel:Remove()
end)
end
ix.gui.craftingpanel = craftingPanel
ix.gui.activeSkill = craftingPanel
end)

View File

@@ -0,0 +1,44 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PANEL = {}
function PANEL:Init()
local parent = self:GetParent():GetParent()
self:SetSize(parent.contentPanel:GetSize())
-- Config
self.firstTitle = "Level Unlocks"
self.skill = "guns"
-- Create titles
self:Add("CraftingBaseTopTitleBase")
-- Create inner content
self:Add("CraftingBaseInnerContent")
-- Rebuild inner content
self:Add("CraftingBaseRebuild")
end
vgui.Register("GunsBasePanel", PANEL, "EditablePanel")
local function CreateGunsPanel(container)
local panel = container:Add("GunsBasePanel")
ix.gui.gunspanel = panel
ix.gui.activeSkill = panel
return container
end
hook.Add("CreateSkillPanels", "GunsBasePanel", function(tabs)
tabs[ix.skill.list["guns"].uniqueID] = CreateGunsPanel
end)

View File

@@ -0,0 +1,58 @@
--[[
| 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 vgui = vgui
local PANEL = {}
function PANEL:Init()
local parent = self:GetParent():GetParent()
self:SetSize(parent.contentPanel:GetSize())
-- Config
self.firstTitle = "Recipes"
self.secondTitle = "Create"
self.thirdTitle = "Preview"
self.nothingSelected = "No item/recipe selected"
self.requirementsTitleText = "Requirements: "
self.ingredientsTitleText = "Ingredients:"
self.skill = "medicine"
self.craftSound = "willardnetworks/skills/skill_medicine.wav"
-- Create titles
self:Add("CraftingBaseTopTitleBase")
-- Create inner content
self:Add("CraftingBaseInnerContent")
-- Rebuild inner content
self:Add("CraftingBaseRebuild")
end
function PANEL:Remove()
if (self.model) then
self.model:Remove()
end
end
vgui.Register("MedicalBasePanel", PANEL, "EditablePanel")
local function CreateMedicalPanel(container)
local panel = container:Add("MedicalBasePanel")
ix.gui.medicalpanel = panel
ix.gui.activeSkill = panel
return container
end
hook.Add("CreateSkillPanels", "MedicalBasePanel", function(tabs)
tabs[ix.skill.list["medicine"].uniqueID] = CreateMedicalPanel
end)

View File

@@ -0,0 +1,44 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PANEL = {}
function PANEL:Init()
local parent = self:GetParent():GetParent()
self:SetSize(parent.contentPanel:GetSize())
-- Config
self.firstTitle = "Level Unlocks"
self.skill = "melee"
-- Create titles
self:Add("CraftingBaseTopTitleBase")
-- Create inner content
self:Add("CraftingBaseInnerContent")
-- Rebuild inner content
self:Add("CraftingBaseRebuild")
end
vgui.Register("MeleeBasePanel", PANEL, "EditablePanel")
local function CreateMeleePanel(container)
local panel = container:Add("MeleeBasePanel")
ix.gui.gunspanel = panel
ix.gui.activeSkill = panel
return container
end
hook.Add("CreateSkillPanels", "MeleeBasePanel", function(tabs)
tabs[ix.skill.list["melee"].uniqueID] = CreateMeleePanel
end)

View File

@@ -0,0 +1,56 @@
--[[
| 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 vgui = vgui
local PANEL = {}
function PANEL:Init()
local parent = self:GetParent():GetParent()
self:SetSize(parent.contentPanel:GetSize())
-- Config
self.firstTitle = "Items"
self.secondTitle = "Info"
self.thirdTitle = "Preview"
self.nothingSelected = "No item selected"
self.requirementsTitleText = "Requirements: "
self.skill = "smuggling"
-- Create titles
self:Add("CraftingBaseTopTitleBase")
-- Create inner content
self:Add("CraftingBaseInnerContent")
-- Rebuild inner content
self:Add("CraftingBaseRebuild")
end
function PANEL:Remove()
if (self.model) then
self.model:Remove()
end
end
vgui.Register("SmugglingBasePanel", PANEL, "EditablePanel")
local function CreateSmugglingPanel(container)
local panel = container:Add("SmugglingBasePanel")
ix.gui.smugglingpanel = panel
ix.gui.activeSkill = panel
return container
end
hook.Add("CreateSkillPanels", "SmugglingBasePanel", function(tabs)
tabs[ix.skill.list["smuggling"].uniqueID] = CreateSmugglingPanel
end)

View File

@@ -0,0 +1,44 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PANEL = {}
function PANEL:Init()
local parent = self:GetParent():GetParent()
self:SetSize(parent.contentPanel:GetSize())
-- Config
self.firstTitle = "Level Unlocks"
self.skill = "speed"
-- Create titles
self:Add("CraftingBaseTopTitleBase")
-- Create inner content
self:Add("CraftingBaseInnerContent")
-- Rebuild inner content
self:Add("CraftingBaseRebuild")
end
vgui.Register("SpeedBasePanel", PANEL, "EditablePanel")
local function CreateSpeedPanel(container)
local panel = container:Add("SpeedBasePanel")
ix.gui.speedpanel = panel
ix.gui.activeSkill = panel
return container
end
hook.Add("CreateSkillPanels", "SpeedBasePanel", function(tabs)
tabs[ix.skill.list["speed"].uniqueID] = CreateSpeedPanel
end)

View File

@@ -0,0 +1,722 @@
--[[
| 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 PLUGIN = PLUGIN
local titlePushDown = SScaleMin(85 / 3)
local fixHeight = SScaleMin(55 / 3)
local scale780 = SScaleMin(780 / 3)
local scale120 = SScaleMin(120 / 3)
function PANEL:Init()
ix.gui.skills = self
local margin = SScaleMin(10 / 3)
local topPushDown = SScaleMin(150 / 3)
self:SetWide(ScrW() - (topPushDown * 2))
local sizeXtitle, sizeYtitle = self:GetWide(), scale120
local sizeXcontent, sizeYcontent = self:GetWide(), (scale780) - fixHeight
self.titlePanel = self:Add("Panel")
self.titlePanel:SetSize(sizeXtitle, sizeYtitle)
self.titlePanel:SetPos(self:GetWide() * 0.5 - self.titlePanel:GetWide() * 0.5)
self.contentPanel = self:Add("Panel")
self.contentPanel:SetSize(sizeXcontent, sizeYcontent)
self.contentPanel:SetPos(self:GetWide() * 0.5 - self.contentPanel:GetWide() * 0.5, titlePushDown)
self:SetTall(scale120 + scale780 - fixHeight + titlePushDown)
self:Center()
local skillsIcon = self.titlePanel:Add("DImage")
skillsIcon:SetImage("willardnetworks/tabmenu/navicons/crafting.png")
skillsIcon:SetSize(SScaleMin(18 / 3), SScaleMin(18 / 3))
skillsIcon:SetPos(0, SScaleMin(3 / 3))
local skillsTitle = self.titlePanel:Add("DLabel")
skillsTitle:SetFont("TitlesFontNoClamp")
skillsTitle:SetText(LocalPlayer():Name() .. "'s Skills")
skillsTitle:SetPos(SScaleMin(26 / 3))
skillsTitle:SizeToContents()
local skillsDesc = self.titlePanel:Add("DLabel")
skillsDesc:SetFont("MenuFontLargerNoClamp")
skillsDesc:SetText("Remember that the maximum combined skill level is " .. ix.config.Get("MaxTotalSkill", 0) .. ".")
skillsDesc:SetTextColor(Color(200, 200, 200, 255))
skillsDesc:SetPos(0, SScaleMin(25 / 3) + margin * 0.7)
skillsDesc:SizeToContents()
local skillsDesc2 = self.titlePanel:Add("DLabel")
skillsDesc2:SetFont("MenuFontLargerBoldNoFix")
skillsDesc2:SetTextColor(Color(255, 78, 69, 255))
skillsDesc2:SetText("Skill levels: " .. LocalPlayer():GetCharacter():GetTotalSkillLevel() .. "/" .. ix.config.Get("MaxTotalSkill", 0))
skillsDesc2:SetPos(0, SScaleMin(42 / 3) + margin * 0.7)
skillsDesc2:SizeToContents()
self:CreateAttributesPanel()
self.panels = {}
hook.Run("CreateSkillPanels", self.panels) -- Create subpanels for example Crafting
self:CreateSkills()
end
function PANEL:CreateSkills()
if (self.skillPanels) then
for _, v in ipairs(self.skillPanels) do
v:Remove()
end
end
self.skillPanels = {}
local character = LocalPlayer():GetCharacter()
self.skillGrid = self.contentPanel:Add("DGrid")
self.skillGrid:Dock(FILL)
self.skillGrid:SetCols( 3 )
self.skillGrid:SetColWide( self.contentPanel:GetWide() / 3 )
self.skillGrid:SetRowHeight( self.contentPanel:GetTall() / 3 )
for skillID, skillInfo in SortedPairs(ix.skill.list) do
if character:GetFaction() != FACTION_VORT and skillInfo.name == "Vortessence" then
continue
end
self.skillPanels[skillID] = self:CreateSkillPanel(skillID, skillInfo)
end
end
function PANEL:CreateSkillPanel(skillID, skillInfo)
local bottomPanelH = SScaleMin(35 / 3)
local character = LocalPlayer():GetCharacter()
local skillPanel = vgui.Create("Panel")
skillPanel:SetSize((self.contentPanel:GetWide() / 3) - SScaleMin(10 / 3), (self.contentPanel:GetTall() / 3) - SScaleMin(10 / 3))
skillPanel:Center()
skillPanel.Paint = function(_, w, h)
surface.SetDrawColor(color_white)
surface.SetMaterial(ix.util.GetMaterial(skillInfo.image))
surface.DrawTexturedRect(0, 0, w, h - bottomPanelH)
surface.SetDrawColor(ColorAlpha(color_black, 100))
surface.DrawRect(0, h - bottomPanelH, w, bottomPanelH)
surface.SetDrawColor(Color(116, 113, 130, 255))
surface.DrawOutlinedRect(0, 0, w, h)
surface.DrawLine(0, h - bottomPanelH, w, h - bottomPanelH)
end
-- Bottom Panel
local dPadding = SScaleMin(5 / 3)
local bottomPanel = skillPanel:Add("Panel")
bottomPanel:Dock(BOTTOM)
bottomPanel:SetTall(bottomPanelH)
local skillName = bottomPanel:Add("DLabel")
self:CreateSkillLabel(skillName, skillInfo.name, "TitlesFontNoClamp", dPadding * 4, dPadding * 2)
skillPanel.skillLevel = bottomPanel:Add("DLabel")
self:CreateSkillLabel(skillPanel.skillLevel, "Skill Level: " .. character:GetSkillLevel(skillID) .. "/" .. ix.skill.MAX_SKILL, "MenuFontLargerNoClamp", 0, 0, Color(255, 204, 0, 255))
local experiencePanel = bottomPanel:Add("Panel")
experiencePanel:Dock(RIGHT)
experiencePanel:SetWide(SScaleMin(200 / 3))
experiencePanel:DockMargin(dPadding * 2, dPadding, dPadding * 4, dPadding)
experiencePanel:DockPadding(dPadding, dPadding, dPadding, dPadding)
experiencePanel.Paint = function(_, w, h)
surface.SetDrawColor(ColorAlpha(color_black, 100))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(116, 113, 130, 255))
surface.DrawOutlinedRect(0, 0, w, h)
end
local skillProgress = math.Clamp(character:GetSkillStoredExp(skillID) / 1000, 0, 1)
skillPanel.progressBar = experiencePanel:Add("Panel")
skillPanel.progressBar:Dock(FILL)
skillPanel.progressBar.progress = skillProgress
skillPanel.progressBar.Paint = function(panel, w, h)
surface.SetDrawColor(Color(255, 78, 70, 255))
surface.DrawRect(0, 0, w * panel.progress, h)
end
skillPanel.processLabel = skillPanel.progressBar:Add("DLabel")
skillPanel.processLabel.skillID = skillID
skillPanel.processLabel.SetupText = function(panel, char)
if (char:GetSkill(skillID) == ix.skill.MAX_SKILL) then
panel:SetText("MAX LEVEL")
elseif (char:GetTotalSkillLevel() == ix.config.Get("MaxTotalSkill")) then
panel:SetText("MAX TOTAL LEVEL")
elseif (char:CanLevelSkill(panel.skillID)) then
panel:SetText("LEVEL UP")
else
local skillProg = math.Clamp(character:GetSkillStoredExp(panel.skillID) / 1000, 0, 1)
panel:SetText((skillProg * 100) .. "%")
end
end
skillPanel.processLabel:SetupText(character)
skillPanel.processLabel:SetFont("MenuFontLargerNoClamp")
skillPanel.processLabel:SetContentAlignment(5)
skillPanel.processLabel:Dock(FILL)
local levelUp = skillPanel.progressBar:Add("DButton")
levelUp:Dock(FILL)
levelUp:SetText("")
levelUp.Paint = nil
levelUp.DoClick = function()
if character:CanLevelSkill(skillID) then
surface.PlaySound("helix/ui/press.wav")
net.Start("ixSkillLevelUp")
net.WriteString(skillID)
net.SendToServer()
end
end
local imagePanel = skillPanel:Add("Panel")
imagePanel:Dock(FILL)
local boostPanel = imagePanel:Add("Panel")
boostPanel:SetSize(skillPanel:GetWide(), skillPanel:GetTall() - bottomPanelH)
boostPanel:DockPadding(dPadding * 4, dPadding * 3, dPadding * 4, dPadding * 4)
boostPanel.Paint = self.CoolHover
local skillButton = imagePanel:Add("DButton")
skillButton:Dock(FILL)
skillButton:SetText("")
skillButton:DockPadding(dPadding * 4, dPadding * 4, dPadding * 4, dPadding * 4)
skillButton.Paint = nil
skillButton.OnCursorEntered = function()
surface.PlaySound("helix/ui/rollover.wav")
boostPanel.Paint = nil
end
skillButton.OnCursorExited = function()
boostPanel.Paint = self.CoolHover
end
skillButton.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
self:OpenSkillPanel(skillInfo)
end
self:CreateBoostInfo(boostPanel, skillInfo)
self:CheckForCurrent(skillInfo)
local autoLevel = skillButton:Add("DButton")
skillPanel.autoLevel = autoLevel
autoLevel.autoLevel = character:GetSkillAutoLevel(skillID)
autoLevel:Dock(BOTTOM)
autoLevel:SetTall(SScaleMin(20 / 3))
autoLevel:SetContentAlignment(4)
autoLevel:SetText("Auto-Level")
autoLevel:SetFont("MenuFontBoldNoClamp")
autoLevel:SetTextInset(SScaleMin(30 / 3), 0)
autoLevel:DockMargin(0, 0, skillPanel:GetWide() * 0.63, 0)
autoLevel.Paint = function(panel, w, h)
surface.SetDrawColor(color_white)
surface.DrawOutlinedRect(0, 0, SScaleMin(20 / 3), h)
if panel.autoLevel then
surface.SetMaterial(ix.util.GetMaterial("willardnetworks/tabmenu/skills_v2/tick.png"))
surface.DrawTexturedRect(SScaleMin(20 / 3) * 0.5 - SScaleMin(15 / 3) * 0.5, SScaleMin(20 / 3) * 0.5 - SScaleMin(10 / 3) * 0.5, SScaleMin(15 / 3), SScaleMin(11 / 3))
end
end
autoLevel.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
net.Start("ixSkillSetAutoLevel")
net.WriteString(skillID)
net.SendToServer()
autoLevel.autoLevel = !autoLevel.autoLevel
end
if skillInfo.name == "Bartering" then
experiencePanel:SetVisible(false)
skillPanel.skillLevel:SetText("You have " .. (istable(character:GetPermits()) and table.Count(character:GetPermits()) or "0") .. " permits active")
skillPanel.skillLevel:SizeToContents()
autoLevel:SetVisible(false)
end
self.skillGrid:AddItem( skillPanel )
return skillPanel
end
function PANEL:OpenSkillPanel(skill)
surface.PlaySound("helix/ui/press.wav")
if self.panels[skill.uniqueID] then
if (self.contentPanel) then
self.contentPanelOriginX, self.contentPanelOriginY = self.contentPanel:GetPos()
self.contentPanel:MoveTo(ScrW(), self.contentPanelOriginY, 1, 0)
end
for k, v in pairs(self.panels) do
if k == skill.uniqueID then
self:CreateNewContent(v, skill.uniqueID)
end
end
end
end
function PANEL:CheckForCurrent(skill)
if self.panels[skill.uniqueID] then
if self.contentPanel then
if LocalPlayer().lastSelectedSkill then
if LocalPlayer().lastSelectedSkill == skill.uniqueID then
self.contentPanelOriginX, self.contentPanelOriginY = self.contentPanel:GetPos()
self.contentPanel:SetPos(ScrW(), self.contentPanelOriginY)
for k, v in pairs(self.panels) do
if k == skill.uniqueID then
self:CreateNewContent(v, skill.uniqueID)
end
end
end
end
end
end
end
function PANEL.CoolHover(self, w, h)
surface.SetDrawColor(Color(0, 0, 0, 150))
surface.DrawRect(0, 0, w, h)
end
function PANEL:CreateBoostInfo(boostPanel, skill)
local character = LocalPlayer():GetCharacter()
local attributes = ix.special.list or {}
local skillAttributes = {}
-- Find the attributes that boost the skill
for _, v in pairs(attributes) do
if v.skills then
if v.skills[skill.uniqueID] then
skillAttributes[v.skills[skill.uniqueID]] = v
end
end
end
if skillAttributes[2] then
local boostedByLabel = boostPanel:Add("DLabel")
boostedByLabel:SetText("Major boost from " .. skillAttributes[2].name)
boostedByLabel:SetFont("MenuFontBoldNoClamp")
boostedByLabel:SetContentAlignment(4)
boostedByLabel:SizeToContents()
boostedByLabel:Dock(TOP)
end
if skillAttributes[1] then
local boostedByLabel = boostPanel:Add("DLabel")
boostedByLabel:SetText("Minor boost from " .. skillAttributes[1].name)
boostedByLabel:SetFont("MenuFontBoldNoClamp")
boostedByLabel:SetContentAlignment(4)
boostedByLabel:SizeToContents()
boostedByLabel:Dock(TOP)
end
local varBoostLevel = character:GetSkillBoostLevels(skill.uniqueID)
local varNeedsLevel, reducedHunger, reducedThirst, reducedGas, reducedHealth = character:GetSkillNeedsReducing(skill.uniqueID)
if (varBoostLevel > 0) then
-- ATLE HAPPY
local boostedLevels = boostPanel:Add("DLabel")
boostedLevels:Dock(TOP)
boostedLevels:SetContentAlignment(4)
boostedLevels:SetFont("MenuFontLargerBoldNoFix")
boostedLevels:SetTextColor(Color(75, 238, 75))
boostedLevels:SetText("Boosted Levels: +" .. varBoostLevel)
boostedLevels:SizeToContents()
end
if (varNeedsLevel > 0) then
if (reducedHunger) then
local hungerReducing = boostPanel:Add("DLabel")
hungerReducing:Dock(TOP)
hungerReducing:SetContentAlignment(4)
hungerReducing:SetFont("MenuFontLargerBoldNoFix")
hungerReducing:SetTextColor(Color(238, 75, 75))
hungerReducing:SetText("-" .. math.Round(reducedHunger, 1) .. " levels due to Hunger")
hungerReducing:SizeToContents()
end
if (reducedThirst) then
local thirstReducing = boostPanel:Add("DLabel")
thirstReducing:Dock(TOP)
thirstReducing:SetContentAlignment(4)
thirstReducing:SetFont("MenuFontLargerBoldNoFix")
thirstReducing:SetTextColor(Color(238, 75, 75))
thirstReducing:SetText("-" .. math.Round(reducedThirst, 1) .. " levels due to Thirst")
thirstReducing:SizeToContents()
end
if (reducedGas) then
local gasReducing = boostPanel:Add("DLabel")
gasReducing:Dock(TOP)
gasReducing:SetContentAlignment(4)
gasReducing:SetFont("MenuFontLargerBoldNoFix")
gasReducing:SetTextColor(Color(238, 75, 75))
gasReducing:SetText("-" .. math.Round(reducedGas, 1) .. " levels due to Spores")
gasReducing:SizeToContents()
end
if (reducedHealth) then
local healthReducing = boostPanel:Add("DLabel")
healthReducing:Dock(TOP)
healthReducing:SetContentAlignment(4)
healthReducing:SetFont("MenuFontLargerBoldNoFix")
healthReducing:SetTextColor(Color(238, 75, 75))
healthReducing:SetText("-" .. math.Round(reducedHealth, 1) .. " levels due to Injuries")
healthReducing:SizeToContents()
end
local needsReducing = boostPanel:Add("DLabel")
needsReducing:Dock(TOP)
needsReducing:SetContentAlignment(4)
needsReducing:SetFont("MenuFontLargerBoldNoFix")
needsReducing:SetTextColor(Color(238, 75, 75))
needsReducing:SetText("Total Reduced Levels: -" .. varNeedsLevel)
needsReducing:SizeToContents()
end
end
function PANEL:CreateSkillLabel(parent, text, font, leftMargin, rightMargin, color)
parent:Dock(LEFT)
parent:SetFont(font)
parent:SetText(text or "")
parent:SetContentAlignment(4)
parent:DockMargin(leftMargin, 0, rightMargin, 0)
parent:SizeToContents()
parent:SetTextColor(color or color_white)
end
function PANEL:CreateNewContent(v, name)
local newContent = self:Add("Panel")
newContent:SetSize(self.contentPanel:GetSize())
newContent:SetPos(self:GetWide() * 0.5 - self.contentPanel:GetWide() * 0.5, titlePushDown)
local x, y = newContent:GetPos()
if !LocalPlayer().lastSelectedSkill then
newContent:SetPos(0 - ScrW(), y)
newContent:MoveTo(x, y, 1, 0)
else
newContent:SetPos(x, y)
end
LocalPlayer().lastSelectedSkill = name
if self.chosenSkillPanel then
self.chosenSkillPanel:Remove()
end
if self.backButton then
self.backButton:Remove()
end
self.chosenSkillPanel = v(newContent)
self.attributesButton:SetVisible(false)
self.backButton = self.titlePanel:Add("DButton")
self.backButton:Dock(RIGHT)
self.backButton:SetText("Return to skills menu")
self.backButton:SetFont("TitlesFontNoClamp")
self.backButton:SetContentAlignment(6)
self.backButton:SetAlpha(0)
self.backButton:AlphaTo(255, 1, 0)
self.backButton:SizeToContents()
self.backButton:DockMargin(0, self.titlePanel:GetTall() * 0.3 - self.backButton:GetTall(), 0, self.titlePanel:GetTall() * 0.5 - self.backButton:GetTall() * 0.5)
self.backButton.Paint = function(_, w, h) end
self.backButton.OnCursorEntered = function()
self.backButton:SetTextColor(Color(200, 200, 200, 255))
surface.PlaySound("willardnetworks/charactercreation/hover.wav")
end
self.backButton.OnCursorExited = function()
self.backButton:SetTextColor(Color(255, 255, 255, 255))
end
self.backButton.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
self.backButton:AlphaTo(0, 1, 0, function()
self.attributesButton:SetVisible(true)
self.attributesButton:SetAlpha(0)
self.attributesButton:AlphaTo(255, 0.5, 0)
end)
newContent:MoveTo(0 - ScrW(), y, 1, 0)
self.contentPanel:MoveTo(self:GetWide() * 0.5 - self.contentPanel:GetWide() * 0.5, self.contentPanelOriginY, 1, 0)
LocalPlayer().lastSelectedSkill = nil
end
end
function PANEL:CreateAttributesPanel()
self.attributesButton = self.titlePanel:Add("DButton")
self.attributesButton:Dock(RIGHT)
self.attributesButton:DockMargin(0, SScaleMin(25 / 3), 0, SScaleMin(63 / 3))
self.attributesButton:SetText("Attribute Boosts")
self.attributesButton:SetFont("MenuFontBoldNoClamp")
self.attributesButton:SetWide(SScaleMin(170 / 3))
self.attributesButton.Paint = function(_, w, h)
surface.SetDrawColor(0, 0, 0, 100)
surface.DrawRect(0, 1, w - 2, h - 1)
surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
surface.DrawOutlinedRect(0, 0, w, h)
end
self.attributesButton.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
self:CreateAttributePopup()
end
end
local attributePadding = SScaleMin(10 / 3)
function PANEL:CreateAttributeBar(parent, attributeID)
local character = LocalPlayer():GetCharacter()
local special = tonumber(character:GetSpecial(attributeID)) or 0
local attribute = ix.special:Find(attributeID)
local icon = attribute.icon or ""
local boost = tonumber(character:GetBoostedAttribute(attributeID)) or 0
local specialBoost = character:GetSpecialBoost()[attributeID] or {}
parent:SetTall(SScaleMin(100 / 3))
parent:Dock(TOP)
parent:DockMargin(attributePadding * 2, 0, attributePadding * 2, attributePadding)
local barPanel = parent:Add("Panel")
barPanel:Dock(TOP)
barPanel:SetTall(SScaleMin(27 / 3))
-- icon
local iconImage = barPanel:Add("DImage")
iconImage:Dock(LEFT)
iconImage:SetWide(SScaleMin(20 / 3))
iconImage:SetImage(icon)
iconImage:DockMargin(0, SScaleMin(2 / 3), attributePadding * 2, SScaleMin(2 / 3))
local backgroundBar = barPanel:Add("Panel")
backgroundBar:Dock(FILL)
backgroundBar.Paint = function(_, w, h)
surface.SetDrawColor(Color(0, 0, 0, 100))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
surface.DrawOutlinedRect(0, 0, w, h)
end
local positivePoints = 0
local negativePoints = 0
for _, v in pairs(specialBoost) do
if v.level > 0 then
positivePoints = positivePoints + v.level
elseif v.level < 0 then
negativePoints = negativePoints - v.level
end
end
local green = Color(138, 200, 97, 255)
local grey = Color(200, 200, 200, 255)
local red = Color(200, 97, 97, 255)
local baseBar = backgroundBar:Add("Panel")
baseBar:SetSize(SScaleMin(360 / 3), barPanel:GetTall())
baseBar.Paint = function(_, w, h)
if positivePoints > 0 then
surface.SetDrawColor(green)
surface.DrawRect(0, 0, (positivePoints + special) * (w / 10), h)
end
if special > 0 then
surface.SetDrawColor(Color(200, 200, 200, 255))
surface.DrawRect(0, 0, (special * w) / 10, h)
end
if negativePoints > 0 then
surface.SetDrawColor(red)
surface.DrawRect(math.max((positivePoints + special) - negativePoints, 0) * (w / 10), 0, negativePoints, h)
end
end
local attributeAmount = barPanel:Add("DLabel")
attributeAmount:Dock(RIGHT)
attributeAmount:SetText(boost .. "/10")
attributeAmount:SetTextColor((boost > special and green) or (boost < special and red) or grey)
attributeAmount:DockMargin(attributePadding * 2 + ((boost == 10 and SScaleMin(3 / 3)) or SScaleMin(11 / 3)), 0, 0, 0)
attributeAmount:SetFont("MenuFontNoClamp")
attributeAmount:SizeToContents()
if specialBoost.long then
local level = specialBoost.long.level
local longBoost = parent:Add("DLabel")
longBoost:Dock(TOP)
if (level != 0) then
local change = level > specialBoost.long.target and "decreasing" or "increasing"
local sign = level > 0 and "+" or ""
longBoost:SetText(string.format("Currently %s%d food boost, %s by 1 in %d minutes", sign, level, change, specialBoost.long.time))
elseif (specialBoost.long.time) then
local sign = specialBoost.long.target > 0 and "+" or "-"
longBoost:SetText(string.format("%s1 food boost becoming active in %d minutes", sign, specialBoost.long.time))
end
longBoost:SetContentAlignment(5)
longBoost:SetFont("MenuFontNoClamp")
longBoost:DockMargin(0, attributePadding, 0, attributePadding)
longBoost:SizeToContents()
end
if specialBoost.short then
local level = specialBoost.short.level
local shortBoost = parent:Add("DLabel")
shortBoost:Dock(TOP)
if (level != 0) then
local change = level > specialBoost.short.target and "decreasing" or "increasing"
local sign = level > 0 and "+" or ""
shortBoost:SetText(string.format("Currently %s%d drug boost, %s by 1 in %d seconds", sign, level, change, specialBoost.short.time))
elseif (specialBoost.short.time) then
local sign = specialBoost.short.target > 0 and "+" or "-"
shortBoost:SetText(string.format("%s1 drug boost becoming active in %d seconds", sign, specialBoost.short.time))
end
shortBoost:SetContentAlignment(5)
shortBoost:SetFont("MenuFontNoClamp")
shortBoost:DockMargin(0, attributePadding, 0, 0)
shortBoost:SizeToContents()
end
if specialBoost.neg then
local negativeBoost = parent:Add("DLabel")
negativeBoost:Dock(TOP)
negativeBoost:SetText("-" .. specialBoost.neg.level .. " from hunger and thirst")
negativeBoost:SetContentAlignment(5)
negativeBoost:SetFont("MenuFontNoClamp")
negativeBoost:DockMargin(0, attributePadding, 0, 0)
negativeBoost:SizeToContents()
end
end
function PANEL:CreateAttributePopup()
if ix.gui.attributeFrame then
ix.gui.attributeFrame:Remove()
end
ix.gui.attributeFrame = vgui.Create("Panel")
local attributeFrame = ix.gui.attributeFrame
attributeFrame:SetSize(SScaleMin(500 / 3), SScaleMin(507 / 3))
attributeFrame:SetAlpha(0)
attributeFrame:AlphaTo(255, 0.5, 0)
attributeFrame:Center()
attributeFrame:MakePopup()
attributeFrame.Paint = function(panel, w, h)
local blur = Material("pp/blurscreen")
local x, y = panel:LocalToScreen(0, 0)
surface.SetDrawColor( 255, 255, 255 )
surface.SetMaterial( blur )
for i = 1, 6 do
blur:SetFloat( "$blur", (i / 6 ) * ( 3 ) )
blur:Recompute()
render.UpdateScreenEffectTexture()
surface.DrawTexturedRect( x * -1, y * -1, ScrW(), ScrH() )
end
surface.SetDrawColor(Color(0, 0, 0, 100))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
surface.DrawOutlinedRect(0, 0, w, h)
end
attributeFrame.Think = function()
if !IsValid(PLUGIN.SkillsMenu) then
ix.gui.attributeFrame:Remove()
end
if ix.gui.attributeFrame then
ix.gui.attributeFrame:MoveToFront()
end
end
local topbar = attributeFrame:Add("Panel")
topbar:SetSize(attributeFrame:GetWide(), SScaleMin(50 / 3))
topbar:Dock(TOP)
topbar:DockMargin(0, 0, 0, attributePadding)
topbar.Paint = function( _, w, h )
surface.SetDrawColor(0, 0, 0, 130)
surface.DrawRect(0, 0, w, h)
end
local titleText = topbar:Add("DLabel")
titleText:SetFont("CharCreationBoldTitleNoClamp")
titleText:Dock(LEFT)
titleText:SetText("Attribute Boosts")
titleText:DockMargin(attributePadding, 0, 0, 0)
titleText:SetContentAlignment(4)
titleText:SizeToContents()
local exit = topbar:Add("DImageButton")
exit:SetImage("willardnetworks/tabmenu/navicons/exit.png")
exit:SetSize(SScaleMin(20 / 3), SScaleMin(20 / 3))
exit:DockMargin(0, SScaleMin(15 / 3), attributePadding, SScaleMin(15 / 3))
exit:Dock(RIGHT)
exit.DoClick = function()
if !IsValid(self) then
return
end
if attributeFrame then
attributeFrame:Remove()
end
surface.PlaySound("helix/ui/press.wav")
end
local strength = attributeFrame:Add("Panel")
self:CreateAttributeBar(strength, "strength")
local intelligence = attributeFrame:Add("Panel")
self:CreateAttributeBar(intelligence, "intelligence")
local perception = attributeFrame:Add("Panel")
self:CreateAttributeBar(perception, "perception")
local agility = attributeFrame:Add("Panel")
self:CreateAttributeBar(agility, "agility")
end
vgui.Register("WNSkillPanel", PANEL, "EditablePanel")
hook.Add("CreateMenuButtons", "WNSkillPanel", function(tabs)
tabs["skills"] = {
RowNumber = 2,
Width = 18,
Height = 18,
Icon = "willardnetworks/tabmenu/navicons/crafting.png",
Create = function(info, container)
if PLUGIN.SkillsMenu then
PLUGIN.SkillsMenu:Remove()
end
PLUGIN.SkillsMenu = container:Add("WNSkillPanel")
end
}
end)

View File

@@ -0,0 +1,54 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
include("shared.lua")
-- Called when the entity initializes.
function ENT:Initialize()
self.fireSize = 100
self.nextFlicker = 0
end
-- Called when the entity should draw.
function ENT:Draw()
self:DrawModel()
end
-- Called when the entity should think.
function ENT:Think()
local curTime = CurTime()
local dlight = DynamicLight( self:EntIndex() )
if (!self.nextFlicker) then
self.nextFlicker = curTime + math.random(0.1, 0.15)
end
if ( dlight ) then
local r, g, b, a = self:GetColor()
dlight.Pos = self:GetPos()
dlight.r = 250
dlight.g = 255
dlight.b = 125
dlight.Brightness = 0
dlight.Size = self.fireSize
dlight.Decay = 5
dlight.DieTime = CurTime() + 0.1
self:Flicker()
end
end
function ENT:Flicker()
local curTime = CurTime()
if (curTime >= self.nextFlicker) then
self.fireSize = math.random(300, 400)
self.nextFlicker = nil
end
end

View File

@@ -0,0 +1,117 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
include("shared.lua")
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
-- Called when the entity initializes.
function ENT:Initialize()
self:SetModel("models/props_junk/rock001a.mdl")
self:PhysicsInit(SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
self:SetMaterial("models/effects/splode1_sheet")
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:Wake()
phys:EnableMotion(false)
end
self:SpawnProps()
self:startFire()
end
-- Called when the entity is spawned.
function ENT:SpawnProps()
local rotation1 = Vector(0, 0, 45)
local angle1 = self:GetAngles()
angle1:RotateAroundAxis(angle1:Forward(), rotation1.z)
local rotation2 = Vector(90, 0, 45)
local angle2 = self:GetAngles()
angle2:RotateAroundAxis(angle2:Up(), rotation2.x)
angle2:RotateAroundAxis(angle2:Forward(), rotation2.z)
local rotation3 = Vector(180, 0, 45)
local angle3 = self:GetAngles()
angle3:RotateAroundAxis(angle3:Up(), rotation3.x)
angle3:RotateAroundAxis(angle3:Forward(), rotation3.z)
local rotation4 = Vector(270, 0, 45)
local angle4 = self:GetAngles()
angle4:RotateAroundAxis(angle4:Up(), rotation4.x)
angle4:RotateAroundAxis(angle4:Forward(), rotation4.z)
local Up = 16
local wood1 = ents.Create("prop_dynamic")
wood1:SetPos(self:GetPos() + self:GetUp() * Up)
wood1:SetAngles(angle1)
wood1:SetModel("models/props_debris/wood_chunk01b.mdl")
wood1:Activate()
wood1:SetParent(self)
wood1:Spawn()
wood1:DeleteOnRemove(self)
local ground = ents.Create("prop_dynamic")
ground:SetPos(self:GetPos())
ground:SetAngles(self:GetAngles())
ground:SetModel("models/willardnetworks/skills/campfire.mdl")
ground:Activate()
ground:SetParent(self)
ground:Spawn()
ground:DeleteOnRemove(self)
local wood2 = ents.Create("prop_dynamic")
wood2:SetPos(self:GetPos() + self:GetUp() * Up)
wood2:SetAngles(angle2)
wood2:SetModel("models/props_debris/wood_chunk01b.mdl")
wood2:Activate()
wood2:SetParent(self)
wood2:Spawn()
wood2:DeleteOnRemove(self)
local wood3 = ents.Create("prop_dynamic")
wood3:SetPos(self:GetPos() + self:GetUp() * Up)
wood3:SetAngles(angle3)
wood3:SetModel("models/props_debris/wood_chunk01b.mdl")
wood3:Activate()
wood3:SetParent(self)
wood3:Spawn()
wood3:DeleteOnRemove(self)
local wood4 = ents.Create("prop_dynamic")
wood4:SetPos(self:GetPos() + self:GetUp() * Up)
wood4:SetAngles(angle4)
wood4:SetModel("models/props_debris/wood_chunk01b.mdl")
wood4:Activate()
wood4:SetParent(self)
wood4:Spawn()
wood4:DeleteOnRemove(self)
end
function ENT:OnRemove()
self:stopFire()
end
function ENT:startFire()
self:Ignite(1)
timer.Create( tostring(self:GetCreationID()), 1, 0,
function()
self:Ignite(1)
end)
end
function ENT:stopFire()
timer.Remove( tostring(self:GetCreationID()) )
self:Extinguish()
end

View File

@@ -0,0 +1,17 @@
--[[
| 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/
--]]
DEFINE_BASECLASS("base_gmodentity");
ENT.Type = "anim";
ENT.Author = "RJ";
ENT.PrintName = "Campfire";
ENT.Spawnable = true;
ENT.AdminSpawnable = true;

View File

@@ -0,0 +1,65 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLUGIN = PLUGIN
include('shared.lua')
netstream.Hook("OpenPickupDispenser", function(boughtItems, entity)
LocalPlayer().activePickupDispenser = entity
LocalPlayer().boughtItems = boughtItems
vgui.Create("PickupDispenser")
end)
netstream.Hook("OpenCIDSelector", function(entity)
LocalPlayer().activePickupDispenser = entity
local cidSelector = vgui.Create("CIDSelector")
cidSelector.activeEntity = entity
cidSelector.ExitCallback = function()
netstream.Start("ClosePanels", LocalPlayer().activePickupDispenser)
LocalPlayer().activePickupDispenser = nil
LocalPlayer().boughtItems = nil
end
cidSelector.SelectCallback = function(idCardID, cid, cidName, entity2)
netstream.Start("SelectCID", idCardID, cid, cidName, entity2)
end
end)
function ENT:Draw()
local position, angles = self:GetPos(), self:GetAngles()
local display = self.Displays[self:GetDisplay()] or self.Displays[6]
angles:RotateAroundAxis(angles:Forward(), 90)
angles:RotateAroundAxis(angles:Right(), 270)
cam.Start3D2D(position + self:GetForward() * 8.4 + self:GetRight()* 8.5 + self:GetUp() * 3, angles, 0.1)
render.PushFilterMin(TEXFILTER.NONE)
render.PushFilterMag(TEXFILTER.NONE)
surface.SetDrawColor(color_black)
surface.DrawRect(10, 16, 153, 40)
surface.SetDrawColor(60, 60, 60)
surface.DrawOutlinedRect(9, 16, 155, 40)
surface.SetDrawColor( Color( 255, 255, 255, 3 ) )
surface.DrawRect( 11, 36 + math.sin( CurTime() * 4 ) * 38 / 2, 151, 1 )
local alpha = 191 + 64 * math.sin( CurTime() * 4 )
local color = ColorAlpha(display[2], alpha)
draw.SimpleText(display[1], "MenuFont", 86, 36, color, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
render.PopFilterMin()
render.PopFilterMag()
cam.End3D2D()
end

View File

@@ -0,0 +1,377 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLUGIN = PLUGIN
AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )
include('shared.lua')
function ENT:SpawnFunction(client, trace)
local dispenser = ents.Create("ix_pickupterminal")
dispenser:SetPos(trace.HitPos)
dispenser:SetAngles(trace.HitNormal:Angle())
dispenser:Spawn()
dispenser:Activate()
ix.saveEnts:SaveEntity(dispenser)
PLUGIN:SavePickupTerminals()
return dispenser
end
ix.log.AddType("pickupDispenserGotItem", function(client)
return string.format("[PICKUP DISPENSER] %s ( %s ) picked up an item from the pickup dispenser.", client:SteamName(), client:Name())
end)
function ENT:Initialize()
-- Because dispenser model has no physics object in order to allow pass through walls
self:SetModel("models/props_junk/watermelon01.mdl")
self:SetSolid(SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:DrawShadow(false)
self:SetUseType(SIMPLE_USE)
self:SetDisplay(1)
self:PhysicsInit(SOLID_VPHYSICS)
self.dispenser = ents.Create("prop_dynamic")
self.dispenser:SetModel("models/props_combine/pickup_dispenser3.mdl")
self.dispenser:SetPos(self:GetPos())
self.dispenser:SetAngles(self:GetAngles())
self.dispenser:SetParent(self)
self.dispenser:Spawn()
self.dispenser:Activate()
self.dispenser:SetTrigger(true)
self:DeleteOnRemove(self.dispenser)
local physics = self.dispenser:GetPhysicsObject()
physics:EnableMotion(false)
physics:Wake()
self.canUse = true
self.nextUseTime = CurTime()
end
function ENT:ItemChoiceLogic(item, inventory, cid, purchasedItems)
if (item == "newspaper_printer") then
if (!inventory:Add(item, 1, {registeredCID = cid:GetData("cid")})) then
return false
end
elseif (item == "apartmentkey" or item == "shopkey") then
local housing = ix.plugin.list["housing"]
if housing and housing.GetApartmentByCID then
local cidData = cid:GetData("cid")
local appID = housing:GetApartmentByCID(cidData, item)
if appID then
if (!inventory:Add(item, 1, {cid = cidData, apartment = appID})) then
return false
end
end
end
elseif (string.find(item, "letter")) then
local itemData = purchasedItems[item]
if (!inventory:Add("paper", 1, {title = itemData.title, writingID = itemData.writingID, owner = itemData.currentOwner})) then
return false
end
else
if (!inventory:Add(item)) then
return false
end
end
return true
end
function ENT:GiveItem(client, item, cid)
local character = client:GetCharacter()
local inventory = character:GetInventory()
local itemTable = string.find(item, "letter") and ix.item.list["paper"] or ix.item.list[item]
if (!itemTable) then return false end
if (!inventory:FindEmptySlot(itemTable.width, itemTable.height)) then
return false
end
if !inventory:GetItemByID(cid.id) then
return false
end
if self.charLoaded then
if ix.char.loaded[self.charLoaded] then
local items = ix.char.loaded[self.charLoaded]:GetPurchasedItems()
if (!items[item] or (!istable(items[item]) and items[item] <= 0)) then
return false
end
if self:ItemChoiceLogic(item, inventory, cid, items) then
ix.char.loaded[self.charLoaded]:SetPurchasedItems(item)
ix.log.Add(client, "pickupDispenserGotItem")
end
end
else
if self.dbGeneric then
local queryObj = mysql:Select("ix_characters_data")
queryObj:Where("id", self.dbGeneric)
queryObj:Where("key", "purchasedItems")
queryObj:Select("data")
queryObj:Callback(function(result)
if (!istable(result) or !result[1]) then return end
if !result[1].data then return end
local items = util.JSONToTable(result[1].data)
if !items[item] then return end
if !istable(items[item]) then
if items[item] > 0 then
items[item] = items[item] - 1
if items[item] == 0 then
items[item] = nil
end
else
return
end
else
if items[item] then items[item] = nil end
end
if self:ItemChoiceLogic(item, inventory, cid, items) then
local updateQuery = mysql:Update("ix_characters_data")
updateQuery:Update("data", util.TableToJSON(items))
updateQuery:Where("id", self.dbGeneric)
updateQuery:Where("key", "purchasedItems")
updateQuery:Execute()
ix.log.Add(client, "pickupDispenserGotItem")
end
end)
queryObj:Execute()
end
end
self:EmitSound("buttons/button1.wav")
self:SetDisplay(3)
return true
end
function ENT:OpenCIDSelector(client)
netstream.Start(client, "OpenCIDSelector", self)
end
function ENT:CreateCombineAlert(client, message)
ix.combineNotify:AddImportantNotification(message, nil, client, self:GetPos())
end
function ENT.OpenDispenserFail(idCard, client, activeDispenser)
if (!IsValid(activeDispenser)) then return end
activeDispenser:SetDisplay(4)
activeDispenser:EmitSound("ambient/machines/combine_terminal_idle1.wav")
activeDispenser.charLoaded = nil
activeDispenser.dbGeneric = nil
activeDispenser.activeCID = nil
timer.Simple(2, function()
if IsValid(activeDispenser) then
activeDispenser:SetDisplay(1)
activeDispenser.canUse = true
end
end)
end
function ENT:CheckForVerdicts(client, idCard, genericData)
if (idCard:GetData("active", false) == false) then
self:CreateCombineAlert(client, "WRN:// Inactive Identification Card #" .. idCard:GetData("cid", 00000) .. " usage attempt detected")
self:SetDisplay(9)
timer.Simple(1.5, function()
if self then
self.OpenDispenserFail(nil, client, self)
end
end)
return
end
local isBOL = genericData.bol
local isAC = genericData.anticitizen
if (isBOL or isAC) then
local text = isBOL and "BOL Suspect" or "Anti-Citizen"
self:CreateCombineAlert(client, "WRN:// " .. text .. " Identification Card activity detected")
if isAC then
self:SetDisplay(9)
timer.Simple(1.5, function()
if self then
self.OpenDispenserFail(nil, client, self)
end
end)
end
return !isAC -- stop if isAC, continue for isBOL
end
return true
end
function ENT.OpenDispenser(idCard, genericData, client, activeTerminal)
if (!IsValid(activeTerminal)) then return end
activeTerminal:EmitSound("buttons/button4.wav")
activeTerminal:SetDisplay(2)
if (activeTerminal:CheckForVerdicts(client, idCard, genericData)) then
timer.Simple(2, function()
if table.IsEmpty(genericData) then
activeTerminal:SetDisplay(9)
activeTerminal:EmitSound("buttons/button2.wav")
timer.Simple(2, function()
if IsValid(activeTerminal) then
activeTerminal.charLoaded = nil
activeTerminal.dbGeneric = nil
activeTerminal.activeCID = nil
activeTerminal:SetDisplay(1)
activeTerminal.canUse = true
end
end)
else
activeTerminal:OnSuccess(idCard, genericData, client)
end
end)
end
end
function ENT:OnSuccess(idCard, genericData, client)
self:SetDisplay(7)
self:EmitSound("ambient/machines/combine_terminal_idle3.wav")
self.activeCID = idCard
if ix.char.loaded[genericData.id] then
self.charLoaded = genericData.id
netstream.Start(client, "OpenPickupDispenser", ix.char.loaded[genericData.id]:GetPurchasedItems(), self)
return
end
local queryObj = mysql:Select("ix_characters_data")
queryObj:Where("id", genericData.id)
queryObj:Where("key", "purchasedItems")
queryObj:Select("data")
queryObj:Callback(function(result)
if (!istable(result) or !result[1]) then return end
if !result[1].data then return end
netstream.Start(client, "OpenPickupDispenser", util.JSONToTable(result[1].data), self)
self.dbGeneric = genericData.id
end)
queryObj:Execute()
end
function ENT:CheckForCID(client)
local idCards = self.activeCharacter:GetInventory():GetItemsByUniqueID("id_card")
if (#idCards > 1) then
self:OpenCIDSelector(client)
return
end
if (#idCards == 1) then
idCards[1]:LoadOwnerGenericData(self.OpenDispenser, self.OpenDispenserFail, client, self)
else
self.canUse = false
self:EmitSound("buttons/button2.wav")
timer.Simple(1, function()
if (IsValid(self)) then
self.canUse = true
end
end)
end
end
function ENT:CheckGlobalUse(client)
if client.CantPlace then
client:NotifyLocalized("You need to wait before you can use this!")
return false
end
client.CantPlace = true
timer.Simple(3, function()
if client then
client.CantPlace = false
end
end)
return true
end
function ENT:CheckLocalUse(client)
if (!self.canUse and IsValid(self.activePlayer) and self.activePlayer:GetCharacter() == self.activeCharacter) then
return false
else
self.canUse = false
self.activePlayer = client
self.activeCharacter = client:GetCharacter()
return true
end
end
function ENT:StartTouch(entity)
if (entity:GetClass() != "ix_item") then return end
if !self.canUse then return end
self.canUse = false
local itemID = entity:GetItemID()
if ix.city:IsDisallowment(itemID) then
self:SetDisplay(11)
self:EmitSound("ambient/machines/combine_terminal_idle1.wav")
timer.Simple(2, function()
if IsValid(self) then
self:SetDisplay(1)
self.canUse = true
end
end)
else
ix.city.main:AddItem(itemID, entity:GetData("stack", 1))
entity:Remove()
self:SetDisplay(10)
self:EmitSound("ambient/machines/combine_terminal_idle1.wav")
timer.Simple(2, function()
if IsValid(self) then
self:SetDisplay(1)
self.canUse = true
end
end)
self:EmitSound("physics/metal/weapon_impact_soft" .. math.random(1, 3) .. ".wav")
end
end
function ENT:OnUse(client)
self:CheckForCID(client)
end
function ENT:Use(client)
if !self:CheckGlobalUse(client) then
return false
end
if !self:CheckLocalUse(client) then
return false
end
self:OnUse(client)
end

View File

@@ -0,0 +1,45 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLUGIN = PLUGIN
ENT.Type = "anim"
ENT.PrintName = "Pickup Terminal"
ENT.Author = "Fruity"
ENT.Contact = "Willard Networks"
ENT.Purpose = "Pickup items bought with certain skills."
ENT.Instructions = "Press E"
ENT.Category = "HL2 RP"
ENT.Spawnable = true
ENT.AdminOnly = true
ENT.PhysgunDisable = true
ENT.bNoPersist = true
ENT.canMalfunction = true
ENT.Displays = {
[1] = {"WAITING FOR CID", Color( 255, 255, 180 ), true},
[2] = {"CHECKING", Color(255, 200, 0)},
[3] = {"DISPENSING", Color(0, 255, 0)},
[4] = {"RELOADING", Color(255, 200, 0)},
[5] = {"OFFLINE", Color(255, 0, 0), true},
[6] = {"WAITING FOR CID", Color( 255, 255, 180 )},
[7] = {"PREPARING", Color(0, 255, 0)},
[8] = {"NO PURCHASED ITEMS", Color(0, 255, 0)},
[9] = {"INVALID CID", Color(255, 0, 0)},
[10] = {"ITEM ADDED", Color(0, 255, 0)},
[11] = {"ITEM REJECTED", Color(255, 0, 0), true},
}
function ENT:SetupDataTables()
self:NetworkVar("Int", 0, "Display")
end

View File

@@ -0,0 +1,564 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLUGIN = PLUGIN
if (SERVER) then
AddCSLuaFile("shared.lua")
end
SWEP.PrintName = "CIVIL ADMINISTRATION PDA"
SWEP.Category = "Half-Life 2"
SWEP.Spawnable= true
SWEP.AdminSpawnable= true
SWEP.AdminOnly = false
SWEP.ViewModelFOV = 70
SWEP.ViewModel = "models/weapons/c_slam.mdl"
SWEP.WorldModel = "models/weapons/c_slam.mdl"
SWEP.ShowViewModel = false
SWEP.ShowWorldModel = false
SWEP.ViewModelFlip = false
SWEP.BobScale = 1
SWEP.SwayScale = 0
SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom = false
SWEP.Weight = 0
SWEP.Slot = 0
SWEP.SlotPos = 1
SWEP.UseHands = true
SWEP.FireWhenLowered = true
SWEP.FiresUnderwater = true
SWEP.DrawAmmo = false
SWEP.CSMuzzleFlashes = 1
SWEP.Base = "weapon_base"
SWEP.IsAlwaysRaised = true
SWEP.HoldType = "knife"
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = -1
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = ""
SWEP.Primary.Damage = 5
SWEP.Primary.Delay = 0.75
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = 0
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = ""
SWEP.Secondary.Delay = 0.5
SWEP.MaxOffFlat = 80 -- Maximum degrees off of flat to be.
SWEP.LastFire = 0
SWEP.IronSightsPos = Vector(0, 0, 0)
SWEP.IronSightsAng = Vector(0, 0, 0)
SWEP.ViewModelBoneMods = {
["ValveBiped.Bip01_R_UpperArm"] = { scale = Vector(1, 1, 1), pos = Vector(-1, 1, 0), angle = Angle(5, 10, 5) },
["ValveBiped.Bip01_L_UpperArm"] = { scale = Vector(1, 1, 1), pos = Vector(-3.5,-1.8, 0.8), angle = Angle(12, -5, 0) },
["Slam_base"] = { scale = Vector(0.001, 0.001, 0.001), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) },
["Detonator"] = { scale = Vector(0.001, 0.001, 0.001), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) }
}
SWEP.VElements = {
["v_element"] = { type = "Model", model = "models/fruity/pda.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(4.68, 2.7514, -1.198), angle = Angle(-90, -50.392, 90), size = Vector(1, 1, 1), color = Color(255, 255, 255, 255), surpresslightning = false, material = "", skin = 0, bodygroup = {} }
}
SWEP.WElements = {
["w_element"] = { type = "Model", model = "models/fruity/pda.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(5, 1.111, 0), angle = Angle(-90, -50.392, 90), size = Vector(1, 1, 1), color = Color(255, 255, 255, 255), surpresslightning = false, material = "", skin = 0, bodygroup = {} }
}
function SWEP:Initialize()
self:SetWeaponHoldType( self.HoldType )
if CLIENT then
// Create a new table for every weapon instance
self.VElements = table.FullCopy( self.VElements )
self.WElements = table.FullCopy( self.WElements )
self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods )
self:SetWeaponHoldType( self.HoldType )
self:CreateModels(self.VElements) // create viewmodels
self:CreateModels(self.WElements) // create worldmodels
// init view model bone build function
if IsValid(self.Owner) then
local vm = self.Owner:GetViewModel()
if IsValid(vm) then
self:ResetBonePositions(vm)
// Init viewmodel visibility
if (self.ShowViewModel == nil or self.ShowViewModel) then
vm:SetColor(Color(255,255,255,255))
else
// we set the alpha to 1 instead of 0 because else ViewModelDrawn stops being called
vm:SetColor(Color(255,255,255,1))
// ^ stopped working in GMod 13 because you have to do Entity:SetRenderMode(1) for translucency to kick in
// however for some reason the view model resets to render mode 0 every frame so we just apply a debug material to prevent it from drawing
vm:SetMaterial("Debug/hsv")
end
end
end
end
end
////////////////////////////////////////////////////
if CLIENT then
SWEP.vRenderOrder = nil
function SWEP:ViewModelDrawn()
local vm = self.Owner:GetViewModel()
if !IsValid(vm) then return end
if (!self.VElements) then return end
self:UpdateBonePositions(vm)
if (!self.vRenderOrder) then
// we build a render order because sprites need to be drawn after models
self.vRenderOrder = {}
for k, v in pairs( self.VElements ) do
if (v.type == "Model") then
table.insert(self.vRenderOrder, 1, k)
elseif (v.type == "Sprite" or v.type == "Quad") then
table.insert(self.vRenderOrder, k)
end
end
end
for k, name in ipairs( self.vRenderOrder ) do
local v = self.VElements[name]
if (!v) then self.vRenderOrder = nil break end
if (v.hide) then continue end
local model = v.modelEnt
local sprite = v.spriteMaterial
if (!v.bone) then continue end
local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )
if (!pos) then continue end
if (v.type == "Model" and IsValid(model)) then
model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
ang:RotateAroundAxis(ang:Up(), v.angle.y)
ang:RotateAroundAxis(ang:Right(), v.angle.p)
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
model:SetAngles(ang)
//model:SetModelScale(v.size)
local matrix = Matrix()
matrix:Scale(v.size)
model:EnableMatrix( "RenderMultiply", matrix )
if (v.material == "") then
model:SetMaterial("")
elseif (model:GetMaterial() != v.material) then
model:SetMaterial( v.material )
end
model:SetSkin(0)
if (v.bodygroup) then
for k, v in pairs( v.bodygroup ) do
if (model:GetBodygroup(k) != v) then
model:SetBodygroup(k, v)
end
end
end
if (v.surpresslightning) then
render.SuppressEngineLighting(true)
end
render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
render.SetBlend(v.color.a/255)
model:DrawModel()
render.SetBlend(1)
render.SetColorModulation(1, 1, 1)
if (v.surpresslightning) then
render.SuppressEngineLighting(false)
end
elseif (v.type == "Sprite" and sprite) then
local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
render.SetMaterial(sprite)
render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
elseif (v.type == "Quad" and v.draw_func) then
local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
ang:RotateAroundAxis(ang:Up(), v.angle.y)
ang:RotateAroundAxis(ang:Right(), v.angle.p)
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
cam.Start3D2D(drawpos, ang, v.size)
v.draw_func( self )
cam.End3D2D()
end
end
end
SWEP.wRenderOrder = nil
function SWEP:DrawWorldModel()
if (self.ShowWorldModel == nil or self.ShowWorldModel) then
end
if (!self.WElements) then return end
if (!self.wRenderOrder) then
self.wRenderOrder = {}
for k, v in pairs( self.WElements ) do
if (v.type == "Model") then
table.insert(self.wRenderOrder, 1, k)
elseif (v.type == "Sprite" or v.type == "Quad") then
table.insert(self.wRenderOrder, k)
end
end
end
if (IsValid(self.Owner)) then
bone_ent = self.Owner
else
// when the weapon is dropped
bone_ent = self
end
for k, name in pairs( self.wRenderOrder ) do
local v = self.WElements[name]
if (!v) then self.wRenderOrder = nil break end
if (v.hide) then continue end
local pos, ang
if (v.bone) then
pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent )
else
pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" )
end
if (!pos) then continue end
local model = v.modelEnt
local sprite = v.spriteMaterial
if (v.type == "Model" and IsValid(model)) then
model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
ang:RotateAroundAxis(ang:Up(), v.angle.y)
ang:RotateAroundAxis(ang:Right(), v.angle.p)
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
model:SetAngles(ang)
//model:SetModelScale(v.size)
local matrix = Matrix()
matrix:Scale(v.size)
model:EnableMatrix( "RenderMultiply", matrix )
if (v.material == "") then
model:SetMaterial("")
elseif (model:GetMaterial() != v.material) then
model:SetMaterial( v.material )
end
model:SetSkin(0)
if (v.bodygroup) then
for k, v in pairs( v.bodygroup ) do
if (model:GetBodygroup(k) != v) then
model:SetBodygroup(k, v)
end
end
end
if (v.surpresslightning) then
render.SuppressEngineLighting(true)
end
render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
render.SetBlend(v.color.a/255)
model:DrawModel()
render.SetBlend(1)
render.SetColorModulation(1, 1, 1)
if (v.surpresslightning) then
render.SuppressEngineLighting(false)
end
elseif (v.type == "Sprite" and sprite) then
local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
render.SetMaterial(sprite)
render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
elseif (v.type == "Quad" and v.draw_func) then
local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
ang:RotateAroundAxis(ang:Up(), v.angle.y)
ang:RotateAroundAxis(ang:Right(), v.angle.p)
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
cam.Start3D2D(drawpos, ang, v.size)
v.draw_func( self )
cam.End3D2D()
end
end
end
function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )
local bone, pos, ang
if (tab.rel and tab.rel != "") then
local v = basetab[tab.rel]
if (!v) then return end
pos, ang = self:GetBoneOrientation( basetab, v, ent )
if (!pos) then return end
pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
ang:RotateAroundAxis(ang:Up(), v.angle.y)
ang:RotateAroundAxis(ang:Right(), v.angle.p)
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
else
bone = ent:LookupBone(bone_override or tab.bone)
if (!bone) then return end
pos, ang = Vector(0,0,0), Angle(0,0,0)
local m = ent:GetBoneMatrix(bone)
if (m) then
pos, ang = m:GetTranslation(), m:GetAngles()
end
if (IsValid(self.Owner) and self.Owner:IsPlayer() and
ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
ang.r = -ang.r // Fixes mirrored models
end
end
return pos, ang
end
function SWEP:CreateModels( tab )
if (!tab) then return end
for k, v in pairs( tab ) do
if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and
string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then
v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
if (IsValid(v.modelEnt)) then
v.modelEnt:SetPos(self:GetPos())
v.modelEnt:SetAngles(self:GetAngles())
v.modelEnt:SetParent(self)
v.modelEnt:SetNoDraw(true)
v.createdModel = v.model
else
v.modelEnt = nil
end
elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite)
and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then
local name = v.sprite.."-"
local params = { ["$basetexture"] = v.sprite }
// make sure we create a unique name based on the selected options
local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
for i, j in pairs( tocheck ) do
if (v[j]) then
params["$"..j] = 1
name = name.."1"
else
name = name.."0"
end
end
v.createdSprite = v.sprite
v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)
end
end
end
local allbones
local hasGarryFixedBoneScalingYet = false
function SWEP:UpdateBonePositions(vm)
if self.ViewModelBoneMods then
if (!vm:GetBoneCount()) then return end
// !! WORKAROUND !! //
// We need to check all model names :/
local loopthrough = self.ViewModelBoneMods
if (!hasGarryFixedBoneScalingYet) then
allbones = {}
for i=0, vm:GetBoneCount() do
local bonename = vm:GetBoneName(i)
if (self.ViewModelBoneMods[bonename]) then
allbones[bonename] = self.ViewModelBoneMods[bonename]
else
allbones[bonename] = {
scale = Vector(1,1,1),
pos = Vector(0,0,0),
angle = Angle(0,0,0)
}
end
end
loopthrough = allbones
end
// !! ----------- !! //
for k, v in pairs( loopthrough ) do
local bone = vm:LookupBone(k)
if (!bone) then continue end
// !! WORKAROUND !! //
local s = Vector(v.scale.x,v.scale.y,v.scale.z)
local p = Vector(v.pos.x,v.pos.y,v.pos.z)
local ms = Vector(1,1,1)
if (!hasGarryFixedBoneScalingYet) then
local cur = vm:GetBoneParent(bone)
while(cur >= 0) do
local pscale = loopthrough[vm:GetBoneName(cur)].scale
ms = ms * pscale
cur = vm:GetBoneParent(cur)
end
end
s = s * ms
// !! ----------- !! //
if vm:GetManipulateBoneScale(bone) != s then
vm:ManipulateBoneScale( bone, s )
end
if vm:GetManipulateBoneAngles(bone) != v.angle then
vm:ManipulateBoneAngles( bone, v.angle )
end
if vm:GetManipulateBonePosition(bone) != p then
vm:ManipulateBonePosition( bone, p )
end
end
else
self:ResetBonePositions(vm)
end
end
function SWEP:ResetBonePositions(vm)
if (!vm:GetBoneCount()) then return end
for i=0, vm:GetBoneCount() do
vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
end
end
function table.FullCopy( tab )
if (!tab) then return nil end
local res = {}
for k, v in pairs( tab ) do
if (type(v) == "table") then
res[k] = table.FullCopy(v)
elseif (type(v) == "Vector") then
res[k] = Vector(v.x, v.y, v.z)
elseif (type(v) == "Angle") then
res[k] = Angle(v.p, v.y, v.r)
else
res[k] = v
end
end
return res
end
end
////////////////////////////////////////////////////
function SWEP:Deploy()
--if !IsValid(self.Owner.C4s) then self.Owner.C4s = {} end
self.Weapon:SendWeaponAnim(ACT_SLAM_TRIPMINE_DRAW)
end
function SWEP:PrimaryAttack()
self:EmitSound( "UI/buttonclick.wav" )
self:SetNextPrimaryFire( CurTime()+2 )
if CLIENT and IsFirstTimePredicted() then
if self.Owner:GetCharacter() then
if self.Owner:GetCharacter():GetFaction() == FACTION_ADMIN then
if IsValid(self.Owner) then
netstream.Start("GetMessageList")
end
end
end
end
end
function SWEP:SecondaryAttack()
end
function SWEP:Holster()
if CLIENT and IsValid(self.Owner) then
local vm = self.Owner:GetViewModel()
if IsValid(vm) then
self:ResetBonePositions(vm)
end
end
return true
end
function SWEP:OnRemove()
self:Holster()
end

View File

@@ -0,0 +1,253 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
AddCSLuaFile()
SWEP.PrintName = "Workbench Placer"
SWEP.Author = "JohnyReaper/Fruity"
SWEP.Purpose = ""
SWEP.Category = "HL2 RP"
SWEP.Slot = 0
SWEP.SlotPos = 1
SWEP.ViewModel = Model("")
SWEP.WorldModel = Model("")
SWEP.ViewModelFOV = 70
SWEP.UseHands = false
SWEP.HoldType = "normal"
SWEP.Ent = "ix_item"
SWEP.BarricadePlace = nil
SWEP.item = false
SWEP.PreviewModel = false
SWEP.Spawnable = true
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = -1
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "none"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
SWEP.DrawAmmo = false
SWEP.IsAlwaysLowered = true
SWEP.FireWhenLowered = true
function SWEP:Initialize()
self:SetWeaponHoldType(self.HoldType)
if CLIENT then
self:GhostProp()
end
end
function SWEP:Deploy()
if CLIENT then
self:GhostProp()
end
end
if (CLIENT) then
SWEP.nextModelRequest = CurTime()
net.Receive("ixRequestWorkBenchGhostModel", function()
local model = net.ReadString()
if LocalPlayer().ghostProp and IsValid(LocalPlayer().ghostProp) then
LocalPlayer().ghostProp:SetModel(model)
end
end)
else
util.AddNetworkString("ixRequestWorkBenchGhostModel")
net.Receive("ixRequestWorkBenchGhostModel", function(_, client)
local weapon = client:GetActiveWeapon()
if IsValid(weapon) and weapon.GetClass and weapon:GetClass() == "weapon_workbench_placer" then
net.Start("ixRequestWorkBenchGhostModel")
net.WriteString(weapon.PreviewModel)
net.Send(client)
end
end)
end
function SWEP:GhostProp()
if (IsValid(self.ghostProp)) then self.ghostProp:Remove() end
self.ghostProp = ents.CreateClientProp()
local curTime = CurTime()
if !self.PreviewModel and self.nextModelRequest <= curTime then
LocalPlayer().ghostProp = self.ghostProp
net.Start("ixRequestWorkBenchGhostModel")
net.SendToServer()
self.nextModelRequest = curTime + 2
return
end
-- self.ghostProp:SetMaterial("models/wireframe")
self.ghostProp:Spawn()
self.ghostProp:Activate()
self.ghostProp:SetParent(self.Owner)
self.ghostProp:SetRenderMode(RENDERMODE_TRANSALPHA)
end
function SWEP:CalcViewModelView(vm, oldPos, oldAng, pos, ang)
local newPos = pos + ang:Up() * 5 + ang:Forward()
return newPos, ang
end
function SWEP:SetInfo(uniqueID, model)
self.item = uniqueID
self.PreviewModel = model
end
function SWEP:PrimaryAttack()
local tr = self.Owner:GetEyeTrace()
if (game.SinglePlayer()) then self:CallOnClient("PrimaryAttack") end
if (SERVER) then
self.Owner:SetAnimation(PLAYER_ATTACK1)
end
if (tr.HitWorld) then
if (!self.BarricadePlace) then
self.BarricadePlace = self.Owner:GetPos() + Angle(0, self.Owner:GetAngles().y, 0):Forward() * 50 + Angle(0, self.Owner:GetAngles().y, 0):Right() * -10 + Angle(0, self.Owner:GetAngles().y, 0):Up()
self.testowyang = Angle(0, self.Owner:GetAngles().y + 180, 0):SnapTo("y", 1)
end
if (SERVER) then
if (self.BarricadePlace) then
local angles = self.testowyang
angles.p = 0
angles.r = 0
angles:RotateAroundAxis(angles:Up(), 360)
if (self.item) then
local client = self:GetOwner()
local char = client.GetCharacter and client:GetCharacter()
local id = char and char.GetID and char:GetID()
local actualItem = char:GetInventory():HasItem(self.item)
if (actualItem) then
actualItem:Remove()
local currentItems = client:GetNetVar("visibleItems", {})
local itemName = ix.item.list[self.item].name
if (currentItems[itemName]) then
currentItems[itemName] = nil
end
client:SetNetVar("visibleItems", currentItems)
if (id) then
ix.item.Spawn(self.item, self.BarricadePlace, function(_, entity)
if IsValid(entity) then
local physObj = entity:GetPhysicsObject()
if IsValid(physObj) then
physObj:EnableMotion( false )
end
end
end, angles, {placer = id})
end
end
end
if (self.Owner.previousWep) then
self.Owner:SelectWeapon(self.Owner.previousWep)
self.Owner.previousWep = nil
end
self:Remove()
end
end
self.Owner:EmitSound("physics/metal/metal_canister_impact_soft"..math.random(1,3)..".wav", 60, 100, 0.5)
end
end
function SWEP:SecondaryAttack()
if (SERVER) then
local char = self.Owner:GetCharacter()
local inventory = char:GetInventory()
if (self.Owner.previousWep) then
self.Owner:SelectWeapon(self.Owner.previousWep)
self.Owner.previousWep = nil
end
self:Remove()
end
end
if (CLIENT) then
function SWEP:DrawHUD()
local ply = LocalPlayer()
if (!ply:Alive()) then return end
draw.SimpleTextOutlined("Press LMB to place", "DermaLarge", ScrW() / 2, ScrH()-230, Color(250,250,250), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER, 1, Color(25, 25, 25, 250))
draw.SimpleTextOutlined("Press RMB to exit", "DermaLarge", ScrW() / 2, ScrH()-200, Color(250,250,250), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER, 1, Color(25, 25, 25, 250))
end
end
function SWEP:Think()
if (CLIENT) then
if (IsValid(self.ghostProp)) then
self.ghostProp:SetPos(self.Owner:GetPos() + Angle(0, self.Owner:GetAngles().y, 0):Forward() * 50 + Angle(0, self.Owner:GetAngles().y, 0):Right() * -10 + Angle(0, self.Owner:GetAngles().y, 0):Up() )
self.ghostProp:SetAngles(Angle(0, self.Owner:GetAngles().y + 180, 0):SnapTo("y", 1))
else
self:GhostProp()
end
end
end
function SWEP:PreDrawViewModel()
if (CLIENT) then
if (!IsValid(self.ghostProp)) then
self:GhostProp()
end
end
end
function SWEP:Holster()
if (CLIENT) then
if (IsValid(self.ghostProp)) then
self.ghostProp:Remove()
end
end
if (SERVER) then
self:Remove()
end
return true
end
function SWEP:OnDrop()
self:Remove()
end
function SWEP:OnRemove()
if (CLIENT) then
if (IsValid(self.ghostProp)) then
self.ghostProp:Remove()
end
end
end

View File

@@ -0,0 +1,21 @@
--[[
| 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.uniqueID = "tool_chembench_assembly"
ITEM.name = "Chemistry Bench Assembly Kit"
ITEM.description = "Alongside a set of instructions, this wooden package contains a high ordeal of different component pieces for Chemistry apperatus."
ITEM.category = "Tools"
ITEM.width = 3
ITEM.height = 3
ITEM.model = "models/props_junk/wood_crate001a.mdl"
ITEM.useSound = "physics/metal/metal_box_break1.wav"
ITEM.openedItem = "tool_chembench"
ITEM.openRequirement = "tool_toolkit"

View File

@@ -0,0 +1,21 @@
--[[
| 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.uniqueID = "tool_craftingbench_assembly"
ITEM.name = "Crafting Bench Assembly Kit"
ITEM.description = "Alongside a set of instructions, this wooden package contains a high ordeal of different component pieces for Crafting apperatus."
ITEM.category = "Tools"
ITEM.width = 3
ITEM.height = 3
ITEM.model = "models/props_junk/wood_crate001a.mdl"
ITEM.useSound = "physics/metal/metal_box_break1.wav"
ITEM.openedItem = "tool_craftingbench"
ITEM.openRequirement = "tool_toolkit"

View File

@@ -0,0 +1,21 @@
--[[
| 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.uniqueID = "tool_distillery_assembly"
ITEM.name = "Distillery Assembly Kit"
ITEM.description = "Alongside a set of instructions, this wooden package contains a high ordeal of different component pieces to create a Distillery."
ITEM.category = "Tools"
ITEM.width = 3
ITEM.height = 3
ITEM.model = "models/props_junk/wood_crate001a.mdl"
ITEM.useSound = "physics/metal/metal_box_break1.wav"
ITEM.openedItem = "tool_distillery"
ITEM.openRequirement = "tool_toolkit"

View File

@@ -0,0 +1,22 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.uniqueID = "tool_metalbench_assembly"
ITEM.name = "Metal Bench Assembly Kit"
ITEM.description = "Alongside a set of instructions, this wooden package contains a high ordeal of different component pieces for Crafting apperatus."
ITEM.category = "Tools"
ITEM.width = 3
ITEM.height = 3
ITEM.model = "models/props_junk/wood_crate001a.mdl"
ITEM.useSound = "physics/metal/metal_box_break1.wav"
ITEM.openedItem = "tool_metalbench"
ITEM.openRequirementAmount = 1
ITEM.openRequirement = "tool_toolkit"

View File

@@ -0,0 +1,21 @@
--[[
| 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.uniqueID = "tool_oven_assembly"
ITEM.name = "Oven Assembly Kit"
ITEM.description = "Alongside a set of instructions, this wooden package contains a high ordeal of different component pieces for Cooking apperatus."
ITEM.category = "Tools"
ITEM.width = 3
ITEM.height = 3
ITEM.model = "models/props_junk/wood_crate001a.mdl"
ITEM.useSound = "physics/metal/metal_box_break1.wav"
ITEM.openedItem = "tool_oven"
ITEM.openRequirement = "tool_toolkit"

View File

@@ -0,0 +1,21 @@
--[[
| 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.uniqueID = "tool_oven_rusty_assembly"
ITEM.name = "Rusty Oven Assembly Kit"
ITEM.description = "Alongside a set of instructions, this wooden package contains a high ordeal of different component pieces for Cooking apperatus."
ITEM.category = "Tools"
ITEM.width = 3
ITEM.height = 3
ITEM.model = "models/props_junk/wood_crate001a.mdl"
ITEM.useSound = "physics/metal/metal_box_break1.wav"
ITEM.openedItem = "tool_oven_rusty"
ITEM.openRequirement = "tool_toolkit"

View File

@@ -0,0 +1,82 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.uniqueID = "base_assembly"
ITEM.name = "Base Assembly Kit"
ITEM.description = "Alongside a set of instructions, this wooden package contains a high ordeal of different component pieces for Crafting apperatus."
ITEM.category = "Tools"
ITEM.width = 3
ITEM.height = 3
ITEM.model = "models/props_junk/wood_crate001a.mdl"
ITEM.useSound = "physics/metal/metal_box_break1.wav"
ITEM.openedItem = "tool_craftingbench"
ITEM.openRequirement = "tool_toolkit"
ITEM.functions.Assemble = {
icon = "icon16/wrench.png",
OnCanRun = function(item)
return !IsValid(item.entity)
end,
OnRun = function(item)
local client = item.player
if (client.CantPlace) then
client:NotifyLocalized("assembleCant")
return false
end
client.CantPlace = true
timer.Simple(3, function()
if (client) then
client.CantPlace = false
end
end)
local character = client:GetCharacter()
local inventory = character:GetInventory()
local requirementTable = ix.item.list[item.openRequirement]
local requirementName = requirementTable.name or item.openRequirement
local openerItem = inventory:HasItem(item.openRequirement)
if (!openerItem) then
client:NotifyLocalized("assembleMissingRequirement", requirementName)
return false
else
if (item.openedItem) then
local openedItemName = ix.item.list[item.openedItem].name or item.openedItem
local openedItemWidth, openedItemHeight = ix.item.list[item.openedItem].width, ix.item.list[item.openedItem].height
timer.Simple(0.25, function()
if (inventory:FindEmptySlot(openedItemWidth, openedItemHeight)) then
inventory:Add(item.openedItem)
if (openerItem.isTool) then
openerItem:DamageDurability(1)
end
client:EmitSound(item.useSound)
client:NotifyLocalized("assembleSuccess", openedItemName)
else
client:NotifyLocalized("assembleNoSpace", openedItemWidth, openedItemHeight)
inventory:Add(item.uniqueID)
end
end)
else
return false
end
end
end
}

View File

@@ -0,0 +1,16 @@
--[[
| 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 = "Crafting Components Base"
ITEM.description = "Just for file structuring, not an item."
ITEM.category = "Crafting Components"
ITEM.base = "base_stackable"
ITEM.maxStackSize = 8

View File

@@ -0,0 +1,13 @@
--[[
| 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 = "Dummy Base"
ITEM.description = "Just for file structuring, not an item."
ITEM.category = "Dummy"

View File

@@ -0,0 +1,13 @@
--[[
| 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 = "Expedition Base"
ITEM.description = "Just for file structuring, not an item."
ITEM.category = "Expedition"

View File

@@ -0,0 +1,16 @@
--[[
| 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 = "Ingredient Base"
ITEM.description = "Just for file structuring, not an item."
ITEM.category = "Ingredients"
ITEM.base = "base_stackable"
ITEM.maxStackSize = 8

View File

@@ -0,0 +1,13 @@
--[[
| 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 = "Junk Base"
ITEM.description = "Just for file structuring, not an item."
ITEM.category = "Junk"

View File

@@ -0,0 +1,227 @@
--[[
| 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 = "Liquor Base"
ITEM.model = Model("models/props_junk/garbage_takeoutcarton001a.mdl")
ITEM.description = "A base for alcoholic consumables."
ITEM.width = 1
ITEM.height = 1
ITEM.category = "Consumable"
ITEM.useSound = {"npc/barnacle/barnacle_crunch3.wav", "npc/barnacle/barnacle_crunch2.wav"}
ITEM.hunger = 0
ITEM.thirst = 0
ITEM.health = 0
ITEM.damage = 0
ITEM.strength = 25
ITEM.abv = 10
ITEM.colorAppendix = {}
ITEM.base = "base_stackable"
ITEM.maxStackSize = 1
ITEM.boosts = {
strength = 3,
agility = -3,
perception = -2,
intelligence = 1
}
ITEM.grade = "LOW" -- ix.inebriation.grades
function ITEM:GetBoostAppend()
local boostAppend = {}
if (self.boosts) then
boostAppend[#boostAppend + 1] = "SHORT-TERM BOOSTS:\n"
if (self.boosts.strength) then
boostAppend[#boostAppend + 1] = string.format("Strength: %d\n", self.boosts.strength)
end
if (self.boosts.agility) then
boostAppend[#boostAppend + 1] = string.format("Agility: %d\n", self.boosts.agility)
end
if (self.boosts.intelligence) then
boostAppend[#boostAppend + 1] = string.format("Intelligence: %d\n", self.boosts.intelligence)
end
if (self.boosts.perception) then
boostAppend[#boostAppend + 1] = string.format("Perception: %d", self.boosts.perception)
end
end
return table.concat(boostAppend, "")
end
function ITEM:GetColorAppendix()
local tbl = {
["yellow"] = self:GetBoostAppend(),
["blue"] = "\nABV: "..tostring(self.abv or 0).."%%"
}
if (self.shotsPerItem and self.shotsPoured) then
tbl["red"] = "Glasses Left: "..tostring(self.shotsPerItem - self.shotsPoured)
end
if (self.grade and ix.inebriation.grades[self.grade]) then
local _grade = ix.inebriation.grades[self.grade]
if (_grade and _grade.appendText) then
tbl["green"] = "Grade: ".._grade.appendText
end
end
return tbl
end
function ITEM:OnInstanced()
if (!self:GetData("stack")) then
self:SetStack(self:GetStackSize())
end
end
local function consume(item, client, character)
if (item.useSound) then
if (istable(item.useSound)) then
client:EmitSound(table.Random(item.useSound))
else
client:EmitSound(item.useSound)
end
end
if item.OnConsume then
item:OnConsume(client, character)
end
if (item.thirst > 0) then
character:SetThirst(math.Clamp(character:GetThirst() - (client:Team() == FACTION_BIRD and item.thirst * 2 or item.thirst), 0, 100))
end
if (item.hunger > 0) then
character:SetHunger(math.Clamp(character:GetHunger() - (client:Team() == FACTION_BIRD and item.hunger * 2 or item.hunger), 0, 100))
end
if (item.health > 0) then
client:SetHealth(math.Clamp(client:Health() + (client:Team() == FACTION_BIRD and item.health * 2 or item.health), 0, client:GetMaxHealth()))
end
if (item.strength > 0) then
if (ix.inebriation and ix.inebriation.allowedFactions[character:GetFaction()]) then
character:SetInebriation(character:GetInebriation() + item.strength)
client:SetNetVar("inebriation", character:GetInebriation())
end
end
if (item.grade) then
local grade = ix.inebriation.grades[item.grade]
if (grade.damage > 0) then
client:SetHealth(math.Clamp(client:Health() - grade.damage, 0, client:GetMaxHealth()))
end
end
if (item.boosts) then
for k, v in pairs(item.boosts) do
character:SetSpecialBoost(k, v, true)
end
end
end
ITEM.functions.Consume = {
icon = "icon16/user.png",
OnRun = function(item)
local client = item.player
local character = item.player:GetCharacter()
consume(item, client, character)
end
}
ITEM.functions.give = {
name = "Use on character",
tip = "giveTip",
icon = "icon16/user_go.png",
OnCanRun = function(item)
if (item.entity) then return false end
local trace = item.player:GetEyeTraceNoCursor()
local target = trace.Entity
if (!IsValid(target)) then
return false
end
if (CLIENT and target:GetClass() == "prop_ragdoll") then
return true
end
if (target:GetClass() == "prop_ragdoll" and IsValid(target.ixPlayer)) then
target = target.ixPlayer
end
if (!target:IsPlayer() or !target:GetCharacter()) then
return false
end
if (target:Health() >= target:GetMaxHealth()) then
local targetChar = target:GetCharacter()
if (targetChar:GetHealing("fakeHealth") == 0 and targetChar:GetBleedout() == -1) then
return false
end
end
return true
end,
OnRun = function(item)
local trace = item.player:GetEyeTraceNoCursor()
local target = trace.Entity
if (target:GetClass() == "prop_ragdoll" and IsValid(target.ixPlayer)) then
target = target.ixPlayer
end
local targetChar = target:GetCharacter()
consume(item, target, targetChar)
end,
}
ITEM.functions.Pour = {
OnCanRun = function(item)
return item.shareable and ix.item.list[item.shotItem]
end,
OnRun = function(item)
local client = item.player
local character = item.player:GetCharacter()
local inventory = character:GetInventory()
local itemName = ix.item.list[item.shotItem] and ix.item.list[item.shotItem].uniqueID or item.shotItem
if (!itemName) then
client:NotifyLocalized("Invalid item.")
return
end
local tr = client:GetEyeTrace()
ix.item.Spawn(itemName, tr.HitPos, function(_item, _)
_item.grade = item.grade or "LOW"
end)
client:NotifyLocalized("You have poured a glass of "..item.name..".")
item.shotsPoured = item.shotsPoured + 1
if (item.shotsPoured >= item.shotsPerItem) then
client:NotifyLocalized("You have poured the last glass of "..item.name..".")
if (item.junk) then
if (!inventory:Add(item.junk)) then
ix.item.Spawn(item.junk, client)
end
end
else
-- don't remove the item if it's not the last shot
return false
end
end
}

View File

@@ -0,0 +1,16 @@
--[[
| 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 = "Medical Components Base"
ITEM.description = "Just for file structuring, not an item."
ITEM.category = "Medical Components"
ITEM.base = "base_stackable"
ITEM.maxStackSize = 4

View File

@@ -0,0 +1,187 @@
--[[
| 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 = "Workbench Base"
ITEM.description = "It is a workbench. Can only be picked up by the first person to place it."
ITEM.category = "Workbenches"
ITEM.isWorkbench = true
ITEM.functions.place = {
name = "Place",
tip = "Place the workbench",
icon = "icon16/brick_add.png",
OnRun = function(item)
local client = item.player
if (!client:Alive()) then return false end
client:EmitSound("physics/cardboard/cardboard_box_break3.wav")
client.previousWep = client:GetActiveWeapon():GetClass()
client:Give("weapon_workbench_placer")
client:SelectWeapon("weapon_workbench_placer")
local weapon = client:GetActiveWeapon()
weapon:SetInfo(item.uniqueID, item.model)
return false
end,
OnCanRun = function(item)
return (!IsValid(item.entity))
end
}
ITEM.functions.Use = {
name = "Use",
icon = "icon16/wrench.png",
OnCanRun = function(itemTable)
return IsValid(itemTable.entity)
end,
OnClick = function(itemTable)
LocalPlayer().lastSelectedSkill = itemTable.workbenchSkill
ix.gui.lastMenuTab = 3
if (!IsValid(ix.gui.menu)) then
vgui.Create("ixMenu")
end
end,
OnRun = function(itemTable)
return false
end
}
ITEM.functions.PackUp = {
name = "Pack Up",
icon = "icon16/box.png",
OnRun = function(item)
local client = item.player
local character = client and IsValid(client) and client.GetCharacter and client:GetCharacter()
local inventory = character:GetInventory()
local toolkit = inventory:HasItem("tool_toolkit")
if (!toolkit) then
client:Notify("You need a toolkit to pack up this workbench!")
return false
end
if (item:GetData("bolted", false)) then
client:Notify("This workbench is bolted down!")
return false
end
local placerData = item:GetData("placer", false)
if placerData and character:GetID() != placerData then
client:Notify("You do not own this workbench!")
return false
end
client:SetAction("Packing up workbench...", 10, function()
if (inventory:Add(item.uniqueID .. "_assembly")) then
toolkit:DamageDurability(1)
client:Notify("Workbench packed up.")
else
client:Notify("You do not have enough inventory space to pack up this workbench!")
return false
end
end)
end,
OnCanRun = function(item)
return !item.noPackUp
end
}
ITEM.functions.Bolt = {
name = "Bolt Workbench",
icon = "icon16/wrench.png",
OnRun = function(item)
local client = item.player
local inventory = client:GetCharacter():GetInventory()
local toolkit = inventory:HasItem("tool_toolkit")
if (!toolkit) then
client:Notify("You need a toolkit to bolt down this workbench!")
return false
end
client:SetAction("Bolting down workbench...", 10, function()
item:SetData("bolted", true)
client:Notify("You bolt down the workbench.")
end)
toolkit:DamageDurability(1)
return false
end,
OnCanRun = function(itemTable)
return itemTable.entity and itemTable.entity:IsValid() and !itemTable:GetData("bolted", false)
end
}
ITEM.functions.UnBolt = {
name = "Unbolt Workbench",
icon = "icon16/wrench_orange.png",
OnRun = function(item)
local client = item.player
if (client:IsAdmin()) then
item:SetData("bolted", false)
client:Notify("Workbench unbolted.")
else
client:Notify("Workbench unbolting requires admin supervision. Please contact one before proceeding!")
end
return false
end,
OnCanRun = function(itemTable)
return itemTable.entity and itemTable.entity:IsValid() and itemTable:GetData("bolted", false)
end
}
ITEM.postHooks.drop = function(item, result)
if (item.player and !item:GetData("placer")) then
item:SetData("placer", item.player:GetCharacter():GetID())
end
end
function ITEM:CanTransfer(oldInventory, newInventory)
local placerData = self:GetData("placer", false)
local newInvOwner = newInventory and newInventory.GetOwner and newInventory:GetOwner()
if newInventory and newInvOwner then
if newInvOwner and IsValid(newInvOwner) then
if placerData and newInvOwner.GetCharacter and newInvOwner:GetCharacter():GetID() != placerData then
newInvOwner:Notify("You are not the owner of this workbench!")
return false
end
end
end
return true
end
function ITEM:OnEntityCreated(entity)
timer.Simple(1, function()
if (IsValid(entity)) then
local physObj = entity:GetPhysicsObject()
physObj:EnableMotion(false)
end
end)
end
function ITEM:OnEntityTakeDamage(entity, damage)
return false
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 = "Arcade Assembly Kit"
ITEM.description = "An assembly kit to put together an arcade machine."
ITEM.category = "misc"
ITEM.width = 3
ITEM.height = 3
ITEM.model = "models/props_junk/wood_crate001a.mdl"
ITEM.colorAppendix = {["red"] = "Contact an admin to convert this into an arcade machine entity."}
ITEM.maxStackSize = 1

View File

@@ -0,0 +1,17 @@
--[[
| 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 = "Building material"
ITEM.description = "Packaged building materials provided by the Combine's Logistical Committee."
ITEM.category = "misc"
ITEM.width = 2
ITEM.height = 2
ITEM.model = "models/props_junk/cardboard_box001a.mdl"
ITEM.maxStackSize = 4

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 = "Checkers Table Assembly Kit"
ITEM.description = "An assembly kit to put together a checkers table."
ITEM.category = "misc"
ITEM.width = 3
ITEM.height = 3
ITEM.model = "models/props_junk/wood_crate001a.mdl"
ITEM.colorAppendix = {["red"] = "Contact an admin to convert this into a checkers table entity."}
ITEM.maxStackSize = 1

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 = "Chess Table Assembly Kit"
ITEM.description = "An assembly kit to put together a chess table."
ITEM.category = "misc"
ITEM.width = 3
ITEM.height = 3
ITEM.model = "models/props_junk/wood_crate001a.mdl"
ITEM.colorAppendix = {["red"] = "Contact an admin to convert this into a chess table entity."}
ITEM.maxStackSize = 1

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/
--]]
ITEM.uniqueID = "comp_charcoal"
ITEM.name = "Charcoal"
ITEM.description = "Some self-made block of charcoal."
ITEM.category = "Crafting"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/willardnetworks/props/charcoal.mdl"
ITEM.colorAppendix = {["blue"] = "This item can be made with the Crafting skill.", ["red"] = "CPs will view you as suspicious if found with this item."}
ITEM.iconCam = {
pos = Vector(1642.86, 1354.28, 862.92),
ang = Angle(22.03, 219.49, 0),
fov = 0.27
}
ITEM.maxStackSize = 8

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/
--]]
ITEM.uniqueID = "comp_charcoal_refill"
ITEM.name = "Charcoal Filter Refill"
ITEM.description = "Some self-made charcoal neatly wrapped in cloth, to be used as a filter."
ITEM.category = "Crafting"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/willardnetworks/props/charcoal.mdl"
ITEM.colorAppendix = {["blue"] = "This item can be made with the Crafting skill."}
ITEM.maxStackSize = 4
ITEM.iconCam = {
pos = Vector(1642.86, 1354.28, 862.92),
ang = Angle(22.03, 219.49, 0),
fov = 0.27
}

View File

@@ -0,0 +1,19 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.uniqueID = "comp_cloth"
ITEM.name = "Cloth Rags"
ITEM.description = "A piece of filthy cloth rags, can be used for crafting."
ITEM.category = "Crafting"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/willardnetworks/skills/cloth.mdl"
ITEM.colorAppendix = {["blue"] = "You can acquire this item via the Crafting skill Breakdown functionality or searching trash piles.", ["red"] = "It is suspicious to carry more than 8 items of this kind."}
ITEM.maxStackSize = 24

View File

@@ -0,0 +1,23 @@
--[[
| 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.uniqueID = "comp_condensed_resin"
ITEM.name = "Condensed Resin"
ITEM.description = "A grey solid cylinder substance that feels soft to the touch. Light-weight and easily breakable... could be used in a compatible machine."
ITEM.category = "Crafting"
ITEM.model = "models/willardnetworks/props_combine/resin_puck.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(173.79, 146.1, 107.55),
ang = Angle(25.1, 219.9, 0),
fov = 3.8
}
ITEM.outlineColor = Color(255, 102, 0)

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 = "Electronic circuits"
ITEM.description = "Scrapped electronic parts. Wonder what these were used for?"
ITEM.category = "Crafting"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/willardnetworks/skills/circuit.mdl"
ITEM.colorAppendix = {["blue"] = "You can acquire this item via the Crafting skill Breakdown functionality or searching trash piles.", ["red"] = "It is suspicious to carry more than 8 items of this kind."}
ITEM.maxStackSize = 24

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.uniqueID = "comp_explosive"
ITEM.name = "High Explosive Material"
ITEM.description = "Some soft explosive compound. Don't go playing with explosives now."
ITEM.category = "Crafting"
ITEM.width = 2
ITEM.height = 1
ITEM.model = "models/willardnetworks/skills/explosive_material.mdl"
ITEM.maxStackSize = 6

View File

@@ -0,0 +1,19 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.uniqueID = "comp_fabric"
ITEM.name = "Fabric"
ITEM.description = "A piece of fabric. It's quite soft."
ITEM.category = "Crafting"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/willardnetworks/skills/fabric.mdl"
ITEM.colorAppendix = {["red"] = "CPs will view you as suspicious if found with this item."}
ITEM.maxStackSize = 8

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/
--]]
ITEM.uniqueID = "comp_iron"
ITEM.name = "Iron"
ITEM.description = "Iron made out of recycled scraps. It is stronger and heavier than before."
ITEM.category = "Crafting"
ITEM.model = "models/willardnetworks/props/reshaped_metal.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(509.64, 427.61, 310.24),
ang = Angle(25, 220, 0),
fov = 1.27
}
ITEM.colorAppendix = {["blue"] = "This item can be made with the Crafting skill.", ["red"] = "CPs will view you as suspicious if found with this item."}
ITEM.maxStackSize = 12

View File

@@ -0,0 +1,19 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.uniqueID = "comp_plastic"
ITEM.name = "Plastic garbage"
ITEM.description = "Elements of plastic waste. Who knows what it was, before."
ITEM.category = "Crafting"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/props_junk/garbage_bag001a.mdl"
ITEM.colorAppendix = {["blue"] = "You can acquire this item via the Crafting skill Breakdown functionality or searching trash piles.", ["red"] = "It is suspicious to carry more than 8 items of this kind."}
ITEM.maxStackSize = 24

View File

@@ -0,0 +1,20 @@
--[[
| 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.uniqueID = "comp_refined_plastic"
ITEM.name = "Plastic Sheets"
ITEM.description = "Plastic sheets. Made from plastic garbage."
ITEM.category = "Crafting"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/props_junk/garbage_bag001a.mdl"
ITEM.colorAppendix = {["blue"] = "This item can be made with the Crafting skill.", ["red"] = "CPs will view you as suspicious if found with this item."}
ITEM.outlineColor = Color(255, 204, 0, 100)
ITEM.maxStackSize = 12

View File

@@ -0,0 +1,23 @@
--[[
| 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.uniqueID = "comp_resin"
ITEM.name = "Resin"
ITEM.description = "A grey solid cylinder substance that feels soft to the touch. Light-weight and easily breakable... could be used in a compatible machine."
ITEM.category = "Crafting"
ITEM.model = "models/willardnetworks/props_combine/resin_puck.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(173.79, 146.1, 107.55),
ang = Angle(25.1, 219.9, 0),
fov = 3.8
}
ITEM.outlineColor = Color(255, 204, 0)

View File

@@ -0,0 +1,20 @@
--[[
| 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.uniqueID = "comp_rivbolts"
ITEM.name = "Box of Rivets and Bolts"
ITEM.description = "A box of sturdy screws, useful for experienced crafters."
ITEM.category = "Crafting"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/willardnetworks/skills/screws.mdl"
ITEM.colorAppendix = {["blue"] = "This item can be made with the Crafting skill.", ["red"] = "CPs will view you as suspicious if found with this item."}
ITEM.outlineColor = Color(255, 204, 0, 100)
ITEM.maxStackSize = 8

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/
--]]
ITEM.uniqueID = "comp_scrap"
ITEM.name = "Scrap Metal"
ITEM.description = "Chunks of scrap metal, useful for crafting."
ITEM.category = "Crafting"
ITEM.model = "models/willardnetworks/props/scrap.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(509.64, 427.61, 310.24),
ang = Angle(25, 220, 0),
fov = 1.27
}
ITEM.colorAppendix = {["blue"] = "You can acquire this item via the Crafting skill Breakdown functionality or searching trash piles.", ["red"] = "It is suspicious to carry more than 8 items of this kind."}
ITEM.maxStackSize = 24

View File

@@ -0,0 +1,19 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.uniqueID = "comp_screws"
ITEM.name = "Box of Screws"
ITEM.description = "A small box of nails. They look a bit rusty."
ITEM.category = "Crafting"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/willardnetworks/skills/screws.mdl"
ITEM.colorAppendix = {["blue"] = "You can acquire this item via the Crafting skill Breakdown functionality or searching trash piles.", ["red"] = "It is suspicious to carry more than 8 items of this kind."}
ITEM.maxStackSize = 24

View File

@@ -0,0 +1,19 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.uniqueID = "comp_steel"
ITEM.name = "Steel"
ITEM.description = "Hardened Steel made by a excellent refiner. Extremely strong and well made."
ITEM.category = "Crafting"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/gibs/scanner_gib02.mdl"
ITEM.colorAppendix = {["blue"] = "This item can be made with the Crafting skill.", ["red"] = "CPs will view you as suspicious if found with this item."}
ITEM.maxStackSize = 8

View File

@@ -0,0 +1,19 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.uniqueID = "comp_stitched_cloth"
ITEM.name = "Stitched Cloth"
ITEM.description = "A piece of stitched cloth. It's tougher than before"
ITEM.category = "Crafting"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/willardnetworks/skills/stitched_cloth.mdl"
ITEM.colorAppendix = {["blue"] = "This item can be made with the Crafting skill.", ["red"] = "CPs will view you as suspicious if found with this item."}
ITEM.maxStackSize = 12

View File

@@ -0,0 +1,20 @@
--[[
| 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.uniqueID = "comp_weapon_parts"
ITEM.name = "Weapon parts"
ITEM.description = "Metal parts for a weapon."
ITEM.category = "Crafting"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/willardnetworks/skills/weaponparts.mdl"
ITEM.outlineColor = Color(255, 204, 0, 100)
ITEM.maxStackSize = 6

View File

@@ -0,0 +1,33 @@
--[[
| 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.uniqueID = "comp_wood"
ITEM.name = "Wooden chippings"
ITEM.description = "A collection of wooden chippings which can be reused for crafting items."
ITEM.category = "Crafting"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/Gibs/wood_gib01a.mdl"
ITEM.colorAppendix = {["blue"] = "You can acquire this item via the Crafting skill Breakdown functionality or searching trash piles.", ["red"] = "It is suspicious to carry more than 8 items of this kind."}
ITEM.maxStackSize = 24
ITEM.functions.Breakdown = {
icon = "icon16/link_break.png",
OnRun = function(item)
local client = item.player
client:GetCharacter():GetInventory():Add("woodstick", 10)
end,
OnCanRun = function(item)
return !IsValid(item.entity) and item.player:Team() == FACTION_BIRD
end
}

View File

@@ -0,0 +1,19 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.name = "Large Container"
ITEM.description = "9x9 sized container. Make sure to contact an admin to setup this container when you've crafted this item."
ITEM.category = "Storage"
ITEM.width = 2
ITEM.height = 4
ITEM.model = "models/props_wasteland/controlroom_storagecloset001a.mdl"
ITEM.colorAppendix = {["red"] = "Contact an admin to convert this into a container. Requires a group of minimum 5 members.", ["blue"] = "We have a limit of 2 small OR 1 medium personal container per player.\nGroups may also get 3 large containers."}
ITEM.maxStackSize = 1

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 = "Large Crate"
ITEM.description = "10x10 sized container. Make sure to contact an admin to setup this container when you've crafted this item."
ITEM.category = "Storage"
ITEM.width = 4
ITEM.height = 4
ITEM.model = "models/props_junk/wood_crate002a.mdl"
ITEM.colorAppendix = {["red"] = "Contact an admin to convert this into a functioning container.", ["blue"] = "As per limitations, you may only have 1 crate owned by yourself."}
ITEM.maxStackSize = 1

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 = "Medium Container"
ITEM.description = "5x8 sized container. Make sure to contact an admin to setup this container when you've crafted this item."
ITEM.category = "Storage"
ITEM.width = 2
ITEM.height = 3
ITEM.model = "models/props_wasteland/controlroom_filecabinet002a.mdl"
ITEM.colorAppendix = {["red"] = "Contact an admin to convert this into a functioning container.", ["blue"] = "We have a limit of 2 small OR 1 medium personal containers per player.\nGroups may also get 3 large containers."}
ITEM.maxStackSize = 1

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 = "Standard Crate"
ITEM.description = "6x6 sized container. Make sure to contact an admin to setup this container when you've crafted this item."
ITEM.category = "Storage"
ITEM.width = 2
ITEM.height = 2
ITEM.model = "models/props_junk/wood_crate001a.mdl"
ITEM.colorAppendix = {["red"] = "Contact an admin to convert this into a functioning container.", ["blue"] = "As per limitations, you may only have 1 crate owned by yourself."}
ITEM.maxStackSize = 1

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 = "Small Container"
ITEM.description = "5x3 sized container. Make sure to contact an admin to setup this container when you've crafted this item."
ITEM.category = "Storage"
ITEM.width = 2
ITEM.height = 2
ITEM.model = "models/props_lab/filecabinet02.mdl"
ITEM.colorAppendix = {["red"] = "Contact an admin to convert this into a functioning container.", ["blue"] = "We have a limit of 2 small OR 1 medium personal containers per player.\nGroups may also get 3 large containers."}
ITEM.maxStackSize = 1

View File

@@ -0,0 +1,47 @@
--[[
| 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.uniqueID = "crafting_water"
ITEM.name = "Crafting Water"
ITEM.description = "A converted can of water used for crafting."
ITEM.category = "Crafting"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/props_junk/popcan01a.mdl"
ITEM.iconCam = {
pos = Vector(509.64, 427.61, 310.24),
ang = Angle(25.01, 220.01, 0),
fov = 0.6
}
ITEM.maxStackSize = 4
ITEM.functions.Convert = {
name = "Convert",
icon = "icon16/wrench.png",
OnRun = function(item)
local client = item.player
local inventory = client:GetCharacter():GetInventory()
local originalID = item:GetData("original")
local original = ix.item.list[originalID]
if (!original) then return end
inventory:Add(originalID, 1, {spoilTime = item:GetData("spoilTime", 0)})
client:Notify("You have converted the Crafting Water back to " .. original.name .. ".")
end,
OnCanRun = function(item)
return item:GetData("original")
end
}
function ITEM:GetDescription()
local item = ix.item.list[self:GetData("original")]
return "A converted " .. (item and item.name or "can of water") .. " used for crafting."
end

View File

@@ -0,0 +1,17 @@
--[[
| 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 = "Pulse Firing Chamber"
ITEM.description = "The main chamber that secures the most fragile part of all Pulse weaponry within it. Important for safety reasons."
ITEM.category = "Crafting"
ITEM.model = "models/props_junk/cardboard_box004a.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.maxStackSize = 2

View File

@@ -0,0 +1,17 @@
--[[
| 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 = "Pulse Firing Mechanism"
ITEM.description = "A firing mechanism for Pulse Weaponry. Important to get Pulse weapons to fire without the Biolock installed."
ITEM.category = "Crafting"
ITEM.model = "models/props_junk/cardboard_box004a.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.maxStackSize = 2

View File

@@ -0,0 +1,17 @@
--[[
| 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 = "Pulse Weaponry - Main Body"
ITEM.description = "The main external body of pulse weaponry. Needs to be placed around internal components"
ITEM.category = "Crafting"
ITEM.model = "models/props_junk/cardboard_box004a.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.maxStackSize = 1

View File

@@ -0,0 +1,17 @@
--[[
| 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 = "Pulse stock"
ITEM.description = "A stock for a pulse weapon... just for the back if making an AR-2 or SR-1"
ITEM.category = "Crafting"
ITEM.model = "models/props_junk/cardboard_box004a.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.maxStackSize = 2

View File

@@ -0,0 +1,17 @@
--[[
| 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.uniqueID = "dummy_biolock_ar2"
ITEM.name = "Biolocked Pulse-Rifle"
ITEM.description = "An Overwatch Pulse-Rifle dropped by a Comine Soldier... it seems to be locked by some form of internal component. It requires a Vortigaunt to unlock this."
ITEM.category = "Dummy"
ITEM.width = 4
ITEM.height = 2
ITEM.model = "models/weapons/w_IRifle.mdl"

View File

@@ -0,0 +1,17 @@
--[[
| 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.uniqueID = "dummy_biolock_psmg"
ITEM.name = "Biolocked Pulse Sub-machine gun"
ITEM.description = "An Overwatch Pulse SMG, a standard weapon of theirs... however not yet usable."
ITEM.category = "Dummy"
ITEM.width = 2
ITEM.height = 2
ITEM.model = "models/weapons/w_IRifle.mdl"

View File

@@ -0,0 +1,17 @@
--[[
| 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.uniqueID = "dummy_biolock_sg1"
ITEM.name = "Biolocked Overwatch Shotgun"
ITEM.description = "The bulky and heavy shotgun of the Overwatch, capable of dealing major damage to not just humans, but also structures."
ITEM.category = "Dummy"
ITEM.width = 4
ITEM.height = 2
ITEM.model = "models/weapons/w_IRifle.mdl"

View File

@@ -0,0 +1,17 @@
--[[
| 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.uniqueID = "dummy_biolock_sr1"
ITEM.name = "Biolocked Ordinal Rifle"
ITEM.description = "An Ordninal Rifle of the Combine Overwatch. Seems to be unusable though."
ITEM.category = "Dummy"
ITEM.width = 4
ITEM.height = 2
ITEM.model = "models/weapons/oar/w_orifle.mdl"

View File

@@ -0,0 +1,17 @@
--[[
| 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.uniqueID = "dummy_biolock_sup"
ITEM.name = "Biolocked Suppressor"
ITEM.description = "The Overwatch Suppressor LMG... generally far too heavy to be carrying around and deadweight."
ITEM.category = "Dummy"
ITEM.width = 5
ITEM.height = 2
ITEM.model = "models/weapons/w_IRifle.mdl"

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.uniqueID = "dummy_emp"
ITEM.name = "Improved EMP Device"
ITEM.description = "A small one-time use EMP device used to disable electronics. It can now also be used on Combine tech- capable of disabling forcefields for 5 minutes, turrets for 10 minutes and disable scanners for good."
ITEM.category = "Dummy"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/Items/car_battery01.mdl"
ITEM.colorAppendix = {["blue"] = "This is an RP item, call a GM to use. This improved version can disable all forms of combine tech- excluding Synthetics or advanced Combine tech"}

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.uniqueID = "dummy_largebomb"
ITEM.name = "Large Bomb"
ITEM.description = "The largest sized bomb one can make out of the scraps available to them in the Outlands with the schematics of old, containing upto 10KG of TNT, this bomb is capable of tearing down multiple buildings at once and causing major damage to a District."
ITEM.category = "Dummy"
ITEM.width = 3
ITEM.height = 3
ITEM.model = "models/Items/car_battery01.mdl"
ITEM.colorAppendix = {["blue"] = "This is an RP item, call a GM to use.", ["red"] = "THIS CANNOT BE SPAWNED OR GIVEN WITHOUT APPROVAL FROM SERVER COUNCIL!"}

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.uniqueID = "dummy_littlebomb"
ITEM.name = "Little Bomb"
ITEM.description = "A small improvised bomb not capable of much damage. Mainly used as a Anti-Personnel Mine or Trap, incapable of destroying a wall. It is made using Composition B explosive at around 13oz."
ITEM.category = "Dummy"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/Items/car_battery01.mdl"
ITEM.colorAppendix = {["blue"] = "This is an RP item, call a GM to use."}

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.uniqueID = "dummy_mediumbomb"
ITEM.name = "Medium Bomb"
ITEM.description = "A medium sized bomb in the shape of a C4 or IED, capable of a force equal to that of 4 kilograms of TNT. Perfectly suited for blowing up buildings or Combine Checkpoints."
ITEM.category = "Dummy"
ITEM.width = 2
ITEM.height = 2
ITEM.model = "models/Items/car_battery01.mdl"
ITEM.colorAppendix = {["blue"] = "This is an RP item, call a GM to use."}

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.uniqueID = "dummy_smallbomb"
ITEM.name = "Small Bomb"
ITEM.description = "Unlike the little bomb, this bomb is capable of producing an explosive worth 1KG worth of TNT. It can blow open walls but may not do much structucal damage to a building. It is also made from Composition B Explosive at around 36oz."
ITEM.category = "Dummy"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/Items/car_battery01.mdl"
ITEM.colorAppendix = {["blue"] = "This is an RP item, call a GM to use."}

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.uniqueID = "expo_battery"
ITEM.name = "Car Battery (Full)"
ITEM.description = ""
ITEM.category = "Expedition"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/Items/car_battery01.mdl"
ITEM.colorAppendix = {["blue"] = "This item is purely RP usage and has no actual ingame function."}

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.uniqueID = "expo_campingbag"
ITEM.name = "Camping Bag"
ITEM.description = "A re-usable piece of kit design for camping. It can fit a max of 3 people for resting."
ITEM.category = "Expedition"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/vj_props/duffle_bag.mdl"
ITEM.colorAppendix = {["blue"] = "This item is purely RP usage and has no actual ingame function."}

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.uniqueID = "expo_settlementkit"
ITEM.name = "Settlment Building Kit"
ITEM.description = "A settlement building kit useful to actually begin building a settlement."
ITEM.category = "Expedition"
ITEM.width = 2
ITEM.height = 2
ITEM.model = "models/props/de_prodigy/concretebags3.mdl"
ITEM.colorAppendix = {["blue"] = "This item is purely RP usage and has no actual ingame function."}

View File

@@ -0,0 +1,22 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.name = "Spiced Dish of Antlion Meat"
ITEM.description = "This dish of otherworldy mixtures of ingredients look strangely rather appetising."
ITEM.category = "Food"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/willardnetworks/food/canned_food4.mdl"
ITEM.hunger = 40
ITEM.boosts = {
strength = 3
}
ITEM.spoil = true
ITEM.useSound = "npc/barnacle/barnacle_crunch2.wav"

View File

@@ -0,0 +1,27 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.name = "Roasted Antlion Meat"
ITEM.description = "A roasted slab of antlion meat, doesn't fill you up as much as you'd like it to, it's quite stringy and carries an odd texture."
ITEM.category = "Food"
ITEM.model = "models/willardnetworks/food/cooked_alienmeat.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(125.61, 104.91, 78.59),
ang = Angle(25.01, 219.94, 0),
fov = 4
}
ITEM.hunger = 30
ITEM.boosts = {
strength = 2
}
ITEM.spoil = true
ITEM.useSound = "npc/barnacle/barnacle_crunch2.wav"

View File

@@ -0,0 +1,41 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.name = "Antlion Sandwich"
ITEM.description = "Slap two pieces of bread together with a slab of antlion meat in-between and you have yourself a sandwich."
ITEM.category = "Food"
ITEM.model = "models/willardnetworks/food/sandwich.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.color = Color(217, 243, 217)
ITEM.iconCam = {
pos = Vector(509.64, 427.61, 310.24),
ang = Angle(24.9, 219.85, 0),
fov = 0.75
}
ITEM.hunger = 45
ITEM.boosts = {
strength = 3,
perception = 1
}
ITEM.spoil = true
ITEM.useSound = "npc/barnacle/barnacle_crunch2.wav"
ITEM.holdData = {
vectorOffset = {
right = -2,
up = 0,
forward = -0.5
},
angleOffset = {
right = 0,
up = 0,
forward = 90
},
}

View File

@@ -0,0 +1,40 @@
--[[
| 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 = "Skewered Antlion Meat"
ITEM.description = "Otherworldly freshness skewed appropriately and ready to eat."
ITEM.category = "Food"
ITEM.model = "models/willardnetworks/food/meatskewer.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(150.5, 126.23, 92.34),
ang = Angle(25.07, 219.54, 0),
fov = 2.7
}
ITEM.hunger = 6
ITEM.boosts = {
strength = 1
}
ITEM.spoil = true
ITEM.useSound = "npc/barnacle/barnacle_crunch2.wav"
ITEM.maxStackSize = 3
ITEM.holdData = {
vectorOffset = {
right = -1.5,
up = 0,
forward = 5
},
angleOffset = {
right = 0,
up = 0,
forward = 90
},
}

View File

@@ -0,0 +1,37 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.name = "Antlion Stew"
ITEM.description = "An otherwordly mixture of meat chunks, vegetables and spice combined to produce a seemingly apetizing stew."
ITEM.category = "Food"
ITEM.model = "models/willardnetworks/food/meatysoup.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(125.61, 104.91, 78.59),
ang = Angle(24.78, 219.86, 0),
fov = 3
}
ITEM.hunger = 65
ITEM.thirst = 15
ITEM.boosts = {
strength = 5
}
ITEM.spoil = true
ITEM.useSound = "ambient/levels/canals/toxic_slime_gurgle4.wav"
ITEM.addVE = 20
function ITEM:OnConsume(client, character)
if character:IsVortigaunt() then
local percentage = ix.config.Get("maxVortalEnergy", 100) / 100
percentage = percentage * self.addVE
character:AddVortalEnergy(percentage)
end
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/
--]]
ITEM.name = "Artificial Cheese Slice"
ITEM.description = "Non-substitute dairy is hard to come by these days, cows are kept around in factories spread throughout the world and arent easy to come by."
ITEM.category = "Food"
ITEM.model = "models/willardnetworks/food/cheesewheel2c.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(169.82, 142.5, 102.64),
ang = Angle(24.34, 220.07, 0),
fov = 1.76
}
ITEM.hunger = 7
ITEM.spoil = true
ITEM.useSound = "npc/barnacle/barnacle_crunch2.wav"

View File

@@ -0,0 +1,42 @@
--[[
| 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 = "Artificial Cheese Paste"
ITEM.description = "White jar of gooey artificial slop, supplemented with cheese for a slightly improved texture and fill."
ITEM.category = "Food"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/props_lab/jar01b.mdl"
ITEM.color = Color(254, 255, 212)
ITEM.hunger = 35
ITEM.boosts = {
perception = 2,
intelligence = 2
}
ITEM.spoil = true
ITEM.useSound = "ambient/levels/canals/toxic_slime_gurgle4.wav"
ITEM.junk = "junk_jar"
ITEM.iconCam = {
pos = Vector(6.22, -199.61, 10.73),
ang = Angle(3.12, 91.84, 0),
fov = 3.64
}
ITEM.holdData = {
vectorOffset = {
right = -1.5,
up = 0,
forward = 0
},
angleOffset = {
right = 0,
up = 0,
forward = 0
},
}

View File

@@ -0,0 +1,27 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.name = "Roasted Artificial Meat"
ITEM.description = "A protein block of Artificial meat for easy consumption."
ITEM.category = "Food"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/willardnetworks/food/steak2.mdl"
ITEM.hunger = 30
ITEM.boosts = {
intelligence = 2
}
ITEM.spoil = true
ITEM.useSound = "npc/barnacle/barnacle_crunch2.wav"
ITEM.iconCam = {
pos = Vector(509.64, 427.61, 310.24),
ang = Angle(24.99, 220.01, 0),
fov = 0.62
}

View File

@@ -0,0 +1,42 @@
--[[
| 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 = "Artificial Meat Paste"
ITEM.description = "White jar of gooey artificial slop, supplemented with bits of artificial meat for improved fill and taste."
ITEM.category = "Food"
ITEM.width = 1
ITEM.height = 1
ITEM.model = "models/props_lab/jar01b.mdl"
ITEM.color = Color(243, 217, 217)
ITEM.hunger = 60
ITEM.boosts = {
strength = 2,
intelligence = 2
}
ITEM.spoil = true
ITEM.useSound = "ambient/levels/canals/toxic_slime_gurgle4.wav"
ITEM.junk = "junk_jar"
ITEM.iconCam = {
pos = Vector(6.22, -199.61, 10.73),
ang = Angle(3.12, 91.84, 0),
fov = 3.64
}
ITEM.holdData = {
vectorOffset = {
right = -1.5,
up = 0,
forward = 0
},
angleOffset = {
right = 0,
up = 0,
forward = 0
},
}

View File

@@ -0,0 +1,40 @@
--[[
| 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 = "Skewered Artificial Meat"
ITEM.description = "A protein block of meat skewed and produced as ready to eat."
ITEM.category = "Food"
ITEM.model = "models/willardnetworks/food/meatskewer2.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(150.5, 126.23, 92.34),
ang = Angle(25.07, 219.54, 0),
fov = 2.7
}
ITEM.hunger = 6
ITEM.boosts = {
intelligence = 1
}
ITEM.spoil = true
ITEM.useSound = "npc/barnacle/barnacle_crunch2.wav"
ITEM.maxStackSize = 3
ITEM.holdData = {
vectorOffset = {
right = -1.5,
up = 0,
forward = 5
},
angleOffset = {
right = 0,
up = 0,
forward = 90
},
}

View File

@@ -0,0 +1,28 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.name = "Artificial Meat Stew"
ITEM.description = "Artificial meat slabs mixed with gravy and an assortment of vegetable chunks."
ITEM.category = "Food"
ITEM.model = "models/willardnetworks/food/meatysoup2.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(125.61, 104.91, 78.59),
ang = Angle(24.78, 219.86, 0),
fov = 3
}
ITEM.hunger = 65
ITEM.thirst = 15
ITEM.boosts = {
intelligence = 5
}
ITEM.spoil = true
ITEM.useSound = "ambient/levels/canals/toxic_slime_gurgle4.wav"

View File

@@ -0,0 +1,27 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.name = "Artificial Meat Stir Fry"
ITEM.description = "Stir fried artificial meat, mixed with salt and noodles."
ITEM.category = "Food"
ITEM.model = "models/willardnetworks/food/canned_food2.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(69.87, 58.63, 44.49),
ang = Angle(24.95, 220, 0),
fov = 4.27
}
ITEM.hunger = 40
ITEM.boosts = {
intelligence = 3
}
ITEM.spoil = true
ITEM.useSound = "npc/barnacle/barnacle_crunch2.wav"

View File

@@ -0,0 +1,28 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.name = "Apple Pie"
ITEM.description = "A pie mixed in with apples. How sweet."
ITEM.category = "Food"
ITEM.model = "models/willardnetworks/food/pie.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(169.82, 142.5, 102.64),
ang = Angle(24.95, 219.95, 0),
fov = 2.78
}
ITEM.hunger = 65
ITEM.boosts = {
strength = 3,
intelligence = 5
}
ITEM.spoil = true
ITEM.useSound = "npc/antlion_grub/squashed.wav"

View File

@@ -0,0 +1,27 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.name = "Bagel"
ITEM.description = "Through inventive means you're able to procure bagels from bread dough, it's somewhat dry but it'll do nicely."
ITEM.model = "models/willardnetworks/food/bagel2.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(509.64, 427.61, 310.24),
ang = Angle(24.94, 219.98, 0),
fov = 0.58
}
ITEM.category = "Food"
ITEM.hunger = 20
ITEM.boosts = {
intelligence = 2
}
ITEM.spoil = true
ITEM.useSound = "npc/barnacle/barnacle_crunch2.wav"

View File

@@ -0,0 +1,82 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.name = "Whole Bread"
ITEM.description = "Even in times such as these, homemade bread can make all the difference."
ITEM.category = "Food"
ITEM.model = "models/willardnetworks/food/bread_loaf.mdl"
ITEM.width = 2
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(258.35, 217.47, 159.76),
ang = Angle(25.18, 220.07, 0),
fov = 2.39
}
ITEM.hunger = 40
ITEM.boosts = {
strength = 3,
}
ITEM.spoil = true
ITEM.holdData = {
vectorOffset = {
right = -2,
up = 0,
forward = 0
},
angleOffset = {
right = 0,
up = 0,
forward = 90
},
}
ITEM.useSound = "npc/barnacle/barnacle_crunch3.wav"
ITEM.openedItem = "baking_bread_half" -- the uniqueID e.g what comes after 'sh_' in the file name unless ITEM.uniqueID is specified
ITEM.openRequirementAmount = 2
ITEM.openRequirements = {"tool_knife", "cleaver", "hatchet", "kitknife", "machete"} -- same desc as above
ITEM.functions.Slice = {
OnRun = function(item)
local client = item.player
local character = item.player:GetCharacter()
local inventory = character:GetInventory()
local openerItem
if (item.openRequirements) then
for k, v in ipairs(item.openRequirements) do
if inventory:HasItem(v) then
openerItem = inventory:HasItem(v)
break
end
end
if !openerItem then
client:NotifyLocalized("You do not have a required tool to assemble this item")
return false
else
if (openerItem.isTool) then
openerItem:DamageDurability(1)
end
end
end
client:EmitSound(item.useSound)
-- Spawn the opened item if it exists
local requirementAmount = item.openRequirementAmount or 1
if (item.openedItem) then
local openedItemName = ix.item.list[item.openedItem].name or item.openedItem
if (!inventory:Add(item.openedItem, requirementAmount)) then
client:NotifyLocalized("You need "..requirementAmount.." inventory spaces to slice this item.")
return
end
client:NotifyLocalized("You have sliced a "..item.name.." and been given a "..openedItemName)
end
end
}

View File

@@ -0,0 +1,82 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.name = "Halved Bread"
ITEM.description = "Half a loaf of bread ready to be consumed."
ITEM.category = "Food"
ITEM.model = "models/willardnetworks/food/bread_half.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(258.35, 217.47, 159.76),
ang = Angle(25.14, 219.92, 0),
fov = 1.49
}
ITEM.hunger = 20
ITEM.boosts = {
strength = 2
}
ITEM.spoil = true
ITEM.holdData = {
vectorOffset = {
right = -2,
up = 0,
forward = 0
},
angleOffset = {
right = 0,
up = 0,
forward = 90
},
}
ITEM.useSound = "npc/barnacle/barnacle_crunch3.wav"
ITEM.openedItem = "baking_bread_slice" -- the uniqueID e.g what comes after 'sh_' in the file name unless ITEM.uniqueID is specified
ITEM.openRequirementAmount = 4
ITEM.openRequirements = {"tool_knife", "cleaver", "hatchet", "kitknife", "machete"} -- same desc as above
ITEM.functions.Slice = {
OnRun = function(item)
local client = item.player
local character = item.player:GetCharacter()
local inventory = character:GetInventory()
local openerItem
if (item.openRequirements) then
for k, v in ipairs(item.openRequirements) do
if inventory:HasItem(v) then
openerItem = inventory:HasItem(v)
break
end
end
if !openerItem then
client:NotifyLocalized("You do not have a required tool to assemble this item")
return false
else
if (openerItem.isTool) then
openerItem:DamageDurability(1)
end
end
end
client:EmitSound(item.useSound)
-- Spawn the opened item if it exists
local requirementAmount = item.openRequirementAmount or 1
if (item.openedItem) then
local openedItemName = ix.item.list[item.openedItem].name or item.openedItem
if (!inventory:Add(item.openedItem, requirementAmount)) then
client:NotifyLocalized("You need "..requirementAmount.." inventory spaces to slice this item.")
return
end
client:NotifyLocalized("You have sliced a "..item.name.." and been given a "..openedItemName)
end
end
}

View File

@@ -0,0 +1,27 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.name = "Bread Slice"
ITEM.description = "A slice of fresh bread. Doesn't fill you up much on its own but it'll do."
ITEM.category = "Food"
ITEM.model = "models/willardnetworks/food/bread_slice.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(258.35, 217.47, 159.76),
ang = Angle(25.26, 220.13, 0),
fov = 1.25
}
ITEM.hunger = 10
ITEM.boosts = {
strength = 1
}
ITEM.spoil = true
ITEM.useSound = "npc/barnacle/barnacle_crunch2.wav"

View File

@@ -0,0 +1,28 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ITEM.name = "Brick Cheesecake"
ITEM.description = "A firm cheesecake, often called the Brick Cheesecake. The scarcity of everyday baking ingredients has led to some rather unconventional outcomes."
ITEM.category = "Food"
ITEM.model = "models/willardnetworks/food/wn_food_cheesecake.mdl"
ITEM.width = 1
ITEM.height = 1
ITEM.iconCam = {
pos = Vector(258.35, 217.47, 159.76),
ang = Angle(25.18, 220.07, 0),
fov = 0.96
}
ITEM.hunger = 65
ITEM.boosts = {
perception = 5,
intelligence = 3
}
ITEM.spoil = true
ITEM.useSound = "npc/antlion_grub/squashed.wav"

Some files were not shown because too many files have changed in this diff Show More