Files
wnsrc/gamemodes/helix/plugins/willardinterface/derma/cl_inventory.lua
lifestorm 94063e4369 Upload
2024-08-04 22:55:00 +03:00

1400 lines
36 KiB
Lua

--[[
| 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 RECEIVER_NAME = "ixInventoryItem"
-- The queue for the rendered icons.
ICON_RENDER_QUEUE = ICON_RENDER_QUEUE or {}
local iconSize = SScaleMin(90 / 3)
local function PaintLockedSlot(slot, w, h)
surface.SetDrawColor(35, 35, 35, 85)
surface.DrawRect(1, 1, w - SScaleMin(2 / 3), h - SScaleMin(2 / 3))
surface.SetDrawColor(80, 80, 80, 255)
surface.DrawOutlinedRect(1, 1, w - SScaleMin(2 / 3), h - SScaleMin(2 / 3))
surface.SetDrawColor(80, 80, 80, 110)
surface.DrawLine( 1, 1, iconSize - SScaleMin(2 / 3), iconSize - SScaleMin(2 / 3) )
surface.DrawLine( 1, iconSize - SScaleMin(2 / 3), iconSize - SScaleMin(2 / 3), 1 )
end
-- To make making inventory variant, This must be followed up.
local function RenderNewIcon(panel, itemTable)
local model = itemTable:GetModel()
-- re-render icons
if ((itemTable.iconCam and !ICON_RENDER_QUEUE[string.utf8lower(model)]) or itemTable.forceRender) then
local iconCam = itemTable.iconCam
iconCam = {
cam_pos = iconCam.pos,
cam_ang = iconCam.ang,
cam_fov = iconCam.fov,
}
ICON_RENDER_QUEUE[string.utf8lower(model)] = true
panel.Icon:RebuildSpawnIconEx(
iconCam
)
end
end
local function InventoryAction(action, itemID, invID, data)
net.Start("ixInventoryAction")
net.WriteString(action)
net.WriteUInt(itemID, 32)
net.WriteUInt(invID, 32)
net.WriteTable(data or {})
net.SendToServer()
end
local PANEL = {}
AccessorFunc(PANEL, "itemTable", "ItemTable")
AccessorFunc(PANEL, "inventoryID", "InventoryID")
function PANEL:Init()
self:Droppable(RECEIVER_NAME)
end
function PANEL:OnMousePressed(code)
if (code == MOUSE_LEFT and self:IsDraggable()) then
self:MouseCapture(true)
self:DragMousePress(code)
self.clickX, self.clickY = input.GetCursorPos()
if (input.IsKeyDown(KEY_LSHIFT)) then
self:DoShiftMove()
end
elseif (code == MOUSE_RIGHT and self.DoRightClick) then
self:DoRightClick()
end
end
function PANEL:OnMouseReleased(code)
-- move the item into the world if we're dropping on something that doesn't handle inventory item drops
if (!dragndrop.m_ReceiverSlot or dragndrop.m_ReceiverSlot.Name != RECEIVER_NAME) then
self:OnDrop(dragndrop.IsDragging())
end
self:DragMouseRelease(code)
self:SetZPos(99)
self:MouseCapture(false)
end
function PANEL:DoShiftMove()
local itemTable = self.itemTable
local inventory = self.inventoryID
local storageInv = ix.gui.openedStorage
if (itemTable and inventory and storageInv and IsValid(storageInv)) then
net.Start("ixInventoryShiftMove")
net.WriteFloat(itemTable.id)
net.WriteFloat(storageInv:GetStorageID())
net.SendToServer()
local path = "willardnetworks/inventory/"
local randomSounds = {"inv_move1.wav", "inv_move2.wav", "inv_move3.wav", "inv_move4.mp3", "inv_move5.mp3", "inv_move6.mp3"}
surface.PlaySound(path .. table.Random(randomSounds))
end
end
function PANEL:DoRightClick()
local itemTable = self.itemTable
local inventory = self.inventoryID
if (itemTable and inventory) then
itemTable.player = LocalPlayer()
local menu = DermaMenu()
local override = hook.Run("CreateItemInteractionMenu", self, menu, itemTable)
if (override == true) then
if (menu.Remove) then
menu:Remove()
end
return
end
for k, v in SortedPairs(itemTable.functions) do
if (k == "drop" or k == "combine" or k == "combined" or (v.OnCanRun and v.OnCanRun(itemTable) == false)) then
continue
end
-- is Multi-Option Function
if (v.isMulti) then
local subMenu, subMenuOption = menu:AddSubMenu(L(v.name or k), function()
itemTable.player = LocalPlayer()
local send = true
if (v.OnClick) then
send = v.OnClick(itemTable)
end
if (v.sound) then
surface.PlaySound(v.sound)
end
if (send != false) then
InventoryAction(k, itemTable.id, inventory)
end
itemTable.player = nil
end)
subMenuOption:SetImage(v.icon or "icon16/brick.png")
if (v.multiOptions) then
local options = isfunction(v.multiOptions) and v.multiOptions(itemTable, LocalPlayer()) or v.multiOptions
for _, sub in pairs(options) do
subMenu:AddOption(L(sub.name or "subOption"), function()
itemTable.player = LocalPlayer()
local send = true
if (sub.OnClick) then
send = sub.OnClick(itemTable)
end
if (sub.sound) then
surface.PlaySound(sub.sound)
end
if (send != false) then
InventoryAction(k, itemTable.id, inventory, sub.data)
end
itemTable.player = nil
end)
end
end
else
menu:AddOption(L(v.name or k), function()
itemTable.player = LocalPlayer()
local send = true
if (v.OnClick) then
send = v.OnClick(itemTable)
end
if (v.sound) then
surface.PlaySound(v.sound)
end
if (send != false) then
InventoryAction(k, itemTable.id, inventory)
end
itemTable.player = nil
end):SetImage(v.icon or "icon16/brick.png")
end
end
-- we want drop to show up as the last option
local info = itemTable.functions.drop
if (info and info.OnCanRun and info.OnCanRun(itemTable) != false) then
menu:AddOption(L(info.name or "drop"), function()
itemTable.player = LocalPlayer()
local send = true
if (info.OnClick) then
send = info.OnClick(itemTable)
end
if (info.sound) then
surface.PlaySound(info.sound)
end
if (send != false) then
InventoryAction("drop", itemTable.id, inventory)
end
itemTable.player = nil
end):SetImage(info.icon or "icon16/brick.png")
end
menu:Open()
for _, v in pairs(menu:GetChildren()[1]:GetChildren()) do
v:SetFont("MenuFontNoClamp")
end
itemTable.player = nil
end
end
local XYchanges = {
[1] = {x = 1, y = 6},
[2] = {x = 1, y = 7},
[3] = {x = 1, y = 8},
[4] = {x = 1, y = 9},
[5] = {x = 1, y = 10},
}
function PANEL:OnDrop(bDragging, inventoryPanel, inventory, gridX, gridY)
local item = self.itemTable
if (!item or !bDragging) then
return
end
if (inventory and inventory.vars and inventory.vars.isEquipSlots) then
if (gridX == 5 and gridY <= 5) then
gridX, gridY = XYchanges[gridY].x, XYchanges[gridY].y
end
end
if (!IsValid(inventoryPanel)) then
local inventoryID = self.inventoryID
if (inventoryID) then
InventoryAction("drop", item.id, inventoryID, {})
end
elseif (inventoryPanel:IsAllEmpty(gridX, gridY, item.width, item.height, self)) then
local oldX, oldY = self.gridX, self.gridY
if (oldX != gridX or oldY != gridY or self.inventoryID != inventoryPanel.invID) then
self:Move(gridX, gridY, inventoryPanel)
end
elseif (inventoryPanel.combineItem) then
local combineItem = inventoryPanel.combineItem
local inventoryID = combineItem.invID
if (inventoryID) then
local info = combineItem.functions.combine
if (info and info.OnCanRun and info.OnCanRun(combineItem, {item.id}) != false) then
combineItem.player = LocalPlayer()
if (combineItem.functions.combine.sound) then
surface.PlaySound(combineItem.functions.combine.sound)
end
InventoryAction("combine", combineItem.id, inventoryID, {item.id})
combineItem.player = nil
end
local info2 = item.functions.combined
if (info2 and info2.OnCanRun and info2.OnCanRun(item, {combineItem.id}) != false) then
item.player = LocalPlayer()
InventoryAction("combined", item.id, inventoryID, {combineItem.id})
item.player = nil
end
end
end
end
function PANEL:Move(newX, newY, givenInventory, bNoSend)
local iconSize2 = givenInventory.iconSize
local oldX, oldY = self.gridX, self.gridY
local oldParent = self:GetParent()
if (givenInventory:OnTransfer(oldX, oldY, newX, newY, oldParent, bNoSend) == false) then
return
end
local isEqSlots = givenInventory:IsEquipSlotsPanel()
local x = (newX - 1 + (isEqSlots and newY > 5 and 4 or 0)) * iconSize2
local y = (newY - 1 - (isEqSlots and newY > 5 and 5 or 0)) * iconSize2 + givenInventory:GetPadding(2)
self.gridX = newX
self.gridY = newY
self:SetParent(givenInventory)
self:SetPos(x, y)
if (self.slots) then
for _, v in ipairs(self.slots) do
if (IsValid(v) and v.item == self) then
v.item = nil
end
end
end
self.slots = {}
for currentX = 1, self.gridW do
for currentY = 1, self.gridH do
local slot = givenInventory.slots[self.gridX + currentX - 1][self.gridY + currentY - 1]
slot.item = self
self.slots[#self.slots + 1] = slot
end
end
local path = "willardnetworks/inventory/"
local randomSounds = {"inv_move1.wav", "inv_move2.wav", "inv_move3.wav", "inv_move4.mp3", "inv_move5.mp3", "inv_move6.mp3"}
surface.PlaySound(path..table.Random(randomSounds))
end
function PANEL:PaintOver(width, height)
local itemTable = self.itemTable
if (itemTable and itemTable.PaintOver) then
itemTable.PaintOver(self, itemTable, width, height)
end
end
function PANEL:ExtraPaint(width, height)
end
function PANEL:Paint(width, height)
surface.SetDrawColor(0, 0, 0, 85)
surface.DrawRect(2, 2, width - 0, height - 4)
self:ExtraPaint(width, height)
end
vgui.Register("ixItemIcon", PANEL, "SpawnIcon")
DEFINE_BASECLASS("DModelPanel")
PANEL = {}
AccessorFunc(PANEL, "itemTable", "ItemTable")
AccessorFunc(PANEL, "inventoryID", "InventoryID")
function PANEL:Init()
self:Droppable(RECEIVER_NAME)
end
function PANEL:OnMousePressed(code)
if (code == MOUSE_LEFT and self:IsDraggable()) then
self:MouseCapture(true)
self:DragMousePress(code)
self.clickX, self.clickY = input.GetCursorPos()
if (input.IsKeyDown(KEY_LSHIFT)) then
self:DoShiftMove()
end
elseif (code == MOUSE_RIGHT and self.DoRightClick) then
self:DoRightClick()
end
end
function PANEL:OnMouseReleased(code)
-- move the item into the world if we're dropping on something that doesn't handle inventory item drops
if (!dragndrop.m_ReceiverSlot or dragndrop.m_ReceiverSlot.Name != RECEIVER_NAME) then
self:OnDrop(dragndrop.IsDragging())
end
self:DragMouseRelease(code)
self:SetZPos(99)
self:MouseCapture(false)
end
function PANEL:DoShiftMove()
local itemTable = self.itemTable
local inventory = self.inventoryID
local storageInv = ix.gui.openedStorage
if (itemTable and inventory and storageInv and IsValid(storageInv)) then
net.Start("ixInventoryShiftMove")
net.WriteFloat(itemTable.id)
net.WriteFloat(storageInv:GetStorageID())
net.SendToServer()
local path = "willardnetworks/inventory/"
local randomSounds = {"inv_move1.wav", "inv_move2.wav", "inv_move3.wav", "inv_move4.mp3", "inv_move5.mp3", "inv_move6.mp3"}
surface.PlaySound(path .. table.Random(randomSounds))
end
end
function PANEL:DoRightClick()
local itemTable = self.itemTable
local inventory = self.inventoryID
if (itemTable and inventory) then
itemTable.player = LocalPlayer()
local menu = DermaMenu()
local override = hook.Run("CreateItemInteractionMenu", self, menu, itemTable)
if (override == true) then
if (menu.Remove) then
menu:Remove()
end
return
end
for k, v in SortedPairs(itemTable.functions) do
if (k == "drop" or k == "combine" or (v.OnCanRun and v.OnCanRun(itemTable) == false)) then
continue
end
-- is Multi-Option Function
if (v.isMulti) then
local subMenu, subMenuOption = menu:AddSubMenu(L(v.name or k), function()
itemTable.player = LocalPlayer()
local send = true
if (v.OnClick) then
send = v.OnClick(itemTable)
end
if (v.sound) then
surface.PlaySound(v.sound)
end
if (send != false) then
InventoryAction(k, itemTable.id, inventory)
end
itemTable.player = nil
end)
subMenuOption:SetImage(v.icon or "icon16/brick.png")
if (v.multiOptions) then
local options = isfunction(v.multiOptions) and v.multiOptions(itemTable, LocalPlayer()) or v.multiOptions
for _, sub in pairs(options) do
subMenu:AddOption(L(sub.name or "subOption"), function()
itemTable.player = LocalPlayer()
local send = true
if (sub.OnClick) then
send = sub.OnClick(itemTable)
end
if (sub.sound) then
surface.PlaySound(sub.sound)
end
if (send != false) then
InventoryAction(k, itemTable.id, inventory, sub.data)
end
itemTable.player = nil
end)
end
end
else
menu:AddOption(L(v.name or k), function()
itemTable.player = LocalPlayer()
local send = true
if (v.OnClick) then
send = v.OnClick(itemTable)
end
if (v.sound) then
surface.PlaySound(v.sound)
end
if (send != false) then
InventoryAction(k, itemTable.id, inventory)
end
itemTable.player = nil
end):SetImage(v.icon or "icon16/brick.png")
end
end
-- we want drop to show up as the last option
local info = itemTable.functions.drop
if (info and info.OnCanRun and info.OnCanRun(itemTable) != false) then
menu:AddOption(L(info.name or "drop"), function()
itemTable.player = LocalPlayer()
local send = true
if (info.OnClick) then
send = info.OnClick(itemTable)
end
if (info.sound) then
surface.PlaySound(info.sound)
end
if (send != false) then
InventoryAction("drop", itemTable.id, inventory)
end
itemTable.player = nil
end):SetImage(info.icon or "icon16/brick.png")
end
menu:Open()
for _, v in pairs(menu:GetChildren()[1]:GetChildren()) do
v:SetFont("MenuFontNoClamp")
end
itemTable.player = nil
end
end
local XYchanges = {
[1] = {x = 1, y = 6},
[2] = {x = 1, y = 7},
[3] = {x = 1, y = 8},
[4] = {x = 1, y = 9},
[5] = {x = 1, y = 10},
}
function PANEL:OnDrop(bDragging, inventoryPanel, inventory, gridX, gridY)
local item = self.itemTable
if (!item or !bDragging) then
return
end
if (inventory and inventory.vars and inventory.vars.isEquipSlots) then
if (gridX == 5 and gridY <= 5) then
gridX, gridY = XYchanges[gridY].x, XYchanges[gridY].y
end
end
if (!IsValid(inventoryPanel)) then
local inventoryID = self.inventoryID
if (inventoryID) then
InventoryAction("drop", item.id, inventoryID, {})
end
elseif (inventoryPanel:IsAllEmpty(gridX, gridY, item.width, item.height, self)) then
local oldX, oldY = self.gridX, self.gridY
if (oldX != gridX or oldY != gridY or self.inventoryID != inventoryPanel.invID) then
self:Move(gridX, gridY, inventoryPanel)
end
elseif (inventoryPanel.combineItem) then
local combineItem = inventoryPanel.combineItem
local inventoryID = combineItem.invID
if (inventoryID) then
local info = combineItem.functions.combine
if (info and info.OnCanRun and info.OnCanRun(combineItem, {item.id}) != false) then
combineItem.player = LocalPlayer()
if (combineItem.functions.combine.sound) then
surface.PlaySound(combineItem.functions.combine.sound)
end
InventoryAction("combine", combineItem.id, inventoryID, {item.id})
combineItem.player = nil
end
local info2 = item.functions.combined
if (info2 and info2.OnCanRun and info2.OnCanRun(item, {combineItem.id}) != false) then
item.player = LocalPlayer()
InventoryAction("combined", item.id, inventoryID, {combineItem.id})
item.player = nil
end
end
end
end
function PANEL:Move(newX, newY, givenInventory, bNoSend)
local iconSize2 = givenInventory.iconSize
local oldX, oldY = self.gridX, self.gridY
local oldParent = self:GetParent()
if (givenInventory:OnTransfer(oldX, oldY, newX, newY, oldParent, bNoSend) == false) then
return
end
local isEqSlots = givenInventory:IsEquipSlotsPanel()
local x = (newX - 1 + (isEqSlots and newY > 5 and 4 or 0)) * iconSize2
local y = (newY - 1 - (isEqSlots and newY > 5 and 5 or 0)) * iconSize2 + givenInventory:GetPadding(2)
self.gridX = newX
self.gridY = newY
self:SetParent(givenInventory)
self:SetPos(x, y)
if (self.slots) then
for _, v in ipairs(self.slots) do
if (IsValid(v) and v.item == self) then
v.item = nil
end
end
end
self.slots = {}
for currentX = 1, self.gridW do
for currentY = 1, self.gridH do
local slot = givenInventory.slots[self.gridX + currentX - 1][self.gridY + currentY - 1]
slot.item = self
self.slots[#self.slots + 1] = slot
end
end
local path = "willardnetworks/inventory/"
local randomSounds = {"inv_move1.wav", "inv_move2.wav", "inv_move3.wav", "inv_move4.mp3", "inv_move5.mp3", "inv_move6.mp3"}
surface.PlaySound(path .. table.Random(randomSounds))
end
function PANEL:PaintOver(width, height)
local itemTable = self.itemTable
if (itemTable and itemTable.PaintOver) then
itemTable.PaintOver(self, itemTable, width, height)
end
end
function PANEL:ExtraPaint(width, height) end
function PANEL:Paint(width, height)
surface.SetDrawColor(0, 0, 0, 85)
surface.DrawRect(2, 2, width - 0, height - 4)
self:ExtraPaint(width, height)
BaseClass.Paint(self, width, height)
end
vgui.Register("ixItemIconAdvanced", PANEL, "DModelPanel")
PANEL = {}
AccessorFunc(PANEL, "iconSize", "IconSize", FORCE_NUMBER)
AccessorFunc(PANEL, "bHighlighted", "Highlighted", FORCE_BOOL)
function PANEL:Init()
self:SetIconSize(iconSize)
self:Receiver(RECEIVER_NAME, self.ReceiveDrop)
self:RequestFocus()
self.Paint = function(this, w, h)
render.ClearDepth() -- Fix for broken DModelPanel item icon depth
surface.SetDrawColor(0, 0, 0, 85)
end
self.panels = {}
end
function PANEL:GetPadding(index)
return select(index, self:GetDockPadding())
end
function PANEL:FitParent(invWidth, invHeight)
local parent = self:GetParent()
if (!IsValid(parent)) then
return
end
local width, height = parent:GetSize()
local padding = 4
local iconSize2
if (invWidth > invHeight) then
iconSize2 = (width - padding * 2) / invWidth
elseif (invHeight > invWidth) then
iconSize2 = (height - padding * 2) / invHeight
else
-- we use height because the titlebar will make it more tall than it is wide
iconSize2 = (height - padding * 2) / invHeight - 4
end
self:SetSize(iconSize2 * invWidth + padding * 2, iconSize2 * invHeight + padding * 2)
self:SetIconSize(iconSize2)
end
function PANEL:OnRemove()
if (self.childPanels) then
for _, v in ipairs(self.childPanels) do
if (v != self) then
v:Remove()
end
end
end
end
function PANEL:ViewOnly()
self.viewOnly = true
for _, icon in pairs(self.panels) do
icon.OnMousePressed = nil
icon.OnMouseReleased = nil
icon.doRightClick = nil
end
end
function PANEL:SetInventory(inventory, bFitParent)
if (inventory.slots) then
local invWidth, invHeight = inventory:GetSize()
self.invID = inventory:GetID()
if (IsValid(ix.gui.inv1) and ix.gui.inv1.childPanels and inventory != LocalPlayer():GetCharacter():GetInventory()) then
self:SetIconSize(ix.gui.inv1:GetIconSize())
self:SetPaintedManually(true)
self.bNoBackgroundBlur = true
ix.gui.inv1.childPanels[#ix.gui.inv1.childPanels + 1] = self
elseif (bFitParent) then
self:FitParent(invWidth, invHeight)
else
self:SetSize(self.iconSize, self.iconSize)
end
self:SetGridSize(invWidth, invHeight)
for x, items in pairs(inventory.slots) do
for y, data in pairs(items) do
if (!data.id) then continue end
local item = ix.item.instances[data.id]
if (item and !IsValid(self.panels[item.id])) then
local icon = self:AddIcon(item, item:GetModel() or "models/props_junk/popcan01a.mdl",
x, y, item.width, item.height, item:GetSkin(), item:GetModelBodygroups(), item.color, item.material, item.rotate, item.OnInventoryDraw)
if (IsValid(icon)) then
icon:SetHelixTooltip(function(tooltip)
ix.hud.PopulateItemTooltip(tooltip, item)
end)
self.panels[item.id] = icon
end
end
end
end
end
end
function PANEL:OnKeyCodePressed(key)
local hoveredPanel = vgui.GetHoveredPanel()
if (hoveredPanel and (hoveredPanel:GetName() == "ixItemIcon" or hoveredPanel:GetName() == "ixItemIconAdvanced")) then
if (key == KEY_Q) then
hoveredPanel:OnDrop(true)
elseif (key == KEY_R) then
local itemTable = hoveredPanel:GetItemTable()
local itemBase = itemTable.base
if (itemBase == "base_ammo") then
InventoryAction("use", itemTable.id, itemTable.invID)
end
end
end
end
function PANEL:SetGridSize(w, h)
local iconSize2 = self.iconSize
local newWidth = w * iconSize2
local newHeight = h * iconSize2 + self:GetPadding(2) + self:GetPadding(4)
self.gridW = w
self.gridH = h
self:SetSize(newWidth, newHeight)
self:BuildSlots()
end
function PANEL:PerformLayout(width, height)
if (self.Sizing and self.gridW and self.gridH) then
local newWidth = (width - 8) / self.gridW
local newHeight = (height - self:GetPadding(2) + self:GetPadding(4)) / self.gridH
self:SetIconSize((newWidth + newHeight) / 2)
self:RebuildItems()
end
end
function PANEL:BuildSlots()
local iconSize2 = self.iconSize
self.slots = self.slots or {}
local function PaintSlot(slot, w, h)
surface.SetDrawColor(35, 35, 35, 85)
surface.DrawRect(1, 1, w - SScaleMin(2 / 3), h - SScaleMin(2 / 3))
surface.SetDrawColor(80, 80, 80, 255)
surface.DrawOutlinedRect(1, 1, w - SScaleMin(2 / 3), h - SScaleMin(2 / 3))
end
for _, v in ipairs(self.slots) do
for _, v2 in ipairs(v) do
v2:Remove()
end
end
self.slots = {}
for x = 1, self.gridW do
self.slots[x] = {}
for y = 1, self.gridH do
local slot = self:Add("DPanel")
slot:SetZPos(-999)
slot.gridX = x
slot.gridY = y
slot:SetPos((x - 1) * iconSize2, (y - 1) * iconSize2 + self:GetPadding(2))
slot:SetSize(iconSize2, iconSize2)
slot.Paint = PaintSlot
self.slots[x][y] = slot
end
end
end
function PANEL:RebuildItems()
local iconSize2 = self.iconSize
for x = 1, self.gridW do
for y = 1, self.gridH do
local slot = self.slots[x][y]
slot:SetPos((x - 1) * iconSize2, (y - 1) * iconSize2 + self:GetPadding(2))
slot:SetSize(iconSize2, iconSize2)
end
end
for _, v in pairs(self.panels) do
if (IsValid(v)) then
v:SetPos(self.slots[v.gridX][v.gridY]:GetPos())
v:SetSize(v.gridW * iconSize2, v.gridH * iconSize2)
end
end
end
function PANEL:PaintDragPreview(width, height, mouseX, mouseY, itemPanel)
local iconSize2 = self.iconSize
local item = itemPanel:GetItemTable()
if (item) then
local inventory = ix.item.inventories[self.invID]
local dropX = math.ceil((mouseX - 0 - (itemPanel.gridW - 1) * 32) / iconSize2)
local dropY = math.ceil((mouseY - self:GetPadding(2) - (itemPanel.gridH - 1) * 32) / iconSize2)
local hoveredPanel = vgui.GetHoveredPanel()
if (IsValid(hoveredPanel) and hoveredPanel != itemPanel and hoveredPanel.GetItemTable) then
local hoveredItem = hoveredPanel:GetItemTable()
if (hoveredItem) then
local info = hoveredItem.functions.combine
local info2 = item.functions.combined
if ((info and info.OnCanRun and info.OnCanRun(hoveredItem, {item.id}) != false) or (info2 and info2.OnCanRun and info2.OnCanRun(item, {hoveredItem.id}) != false)) then
surface.SetDrawColor(ColorAlpha(derma.GetColor("Info", self, Color(200, 0, 0)), 20))
surface.DrawRect(
hoveredPanel.x,
hoveredPanel.y,
hoveredPanel:GetWide(),
hoveredPanel:GetTall()
)
self.combineItem = hoveredItem
return
end
end
end
self.combineItem = nil
local isEquipSlots = inventory.vars and inventory.vars.isEquipSlots or false
-- don't draw grid if we're dragging it out of bounds
if (inventory) then
local invWidth, invHeight = inventory:GetSize()
if (dropX < 1 or dropY < 1 or
dropX - (isEquipSlots and dropX == 5 and 4 or 0) + itemPanel.gridW - 1 > invWidth or
dropY + itemPanel.gridH - 1 > invHeight) then
return
end
end
for x = 0, itemPanel.gridW - 1 do
for y = 0, itemPanel.gridH - 1 do
local x2, y2 = dropX + x, dropY + y
local eqX2, eqY2 = (!isEquipSlots and x2 or 1), (!isEquipSlots and y2 or x2 == 5 and y2 + 5 or y2)
local bEmpty = self:IsEmpty(eqX2, eqY2, itemPanel)
local canMove = (hook.Run("CanMoveItemSameInv", item, inventory, eqX2, eqY2) == true)
if (isEquipSlots and canMove and bEmpty) then
surface.SetDrawColor(0, 255, 0, 10)
elseif (!isEquipSlots and bEmpty) then
surface.SetDrawColor(0, 255, 0, 10)
else
surface.SetDrawColor(255, 255, 0, 10)
end
surface.DrawRect((x2 - 1) * iconSize, (y2 - 1) * iconSize2 + self:GetPadding(2), iconSize2, iconSize2)
end
end
end
end
function PANEL:PaintOver(width, height)
local panel = self.previewPanel
if (IsValid(panel)) then
local itemPanel = (dragndrop.GetDroppable() or {})[1]
if (IsValid(itemPanel)) then
if not (self.slots) then
return
end
self:PaintDragPreview(width, height, self.previewX, self.previewY, itemPanel)
end
end
self.previewPanel = nil
end
function PANEL:IsEmpty(x, y, this)
if (self.slots) then
return (self.slots[x] and self.slots[x][y]) and (!IsValid(self.slots[x][y].item) or self.slots[x][y].item == this)
end
end
function PANEL:IsAllEmpty(x, y, width, height, this)
for x2 = 0, width - 1 do
for y2 = 0, height - 1 do
if (!self:IsEmpty(x + x2, y + y2, this)) then
return false
end
end
end
return true
end
function PANEL:OnTransfer(oldX, oldY, x, y, oldInventory, noSend)
local inventories = ix.item.inventories
local inventory = inventories[oldInventory.invID]
local inventory2 = inventories[self.invID]
local item
if (inventory) then
item = inventory:GetItemAt(oldX, oldY)
if (!item) then
return false
end
if (hook.Run("CanTransferItem", item, inventories[oldInventory.invID], inventories[self.invID], x, y) == false) then
return false, "notAllowed"
end
if (item.CanTransfer and
item:CanTransfer(inventory, inventory != inventory2 and inventory2 or nil) == false) then
return false
end
end
if (!noSend) then
net.Start("ixInventoryMove")
net.WriteUInt(oldX, 6)
net.WriteUInt(oldY, 6)
net.WriteUInt(x, 6)
net.WriteUInt(y, 6)
net.WriteUInt(oldInventory.invID, 32)
net.WriteUInt(self != oldInventory and self.invID or oldInventory.invID, 32)
net.SendToServer()
end
if (inventory) then
inventory.slots[oldX][oldY] = nil
end
if (item and inventory2) then
inventory2.slots[x] = inventory2.slots[x] or {}
inventory2.slots[x][y] = item
end
end
function PANEL:IsEquipSlotsPanel()
local inventory = ix.item.inventories[self.invID]
if inventory and inventory.vars then
if inventory.vars.isEquipSlots then
return true
end
end
return false
end
function PANEL:AddIcon(item, model, x, y, w, h, skin, bodygroups, color, material, bRotate, OnInventoryDraw)
local iconSize2 = self.iconSize
local advanced = color or material or bRotate or OnInventoryDraw
w = w or 1
h = h or 1
if (self.slots[x] and self.slots[x][y]) then
local panel = advanced and self:Add("ixItemIconAdvanced") or self:Add("ixItemIcon")
panel:SetSize(w * iconSize2, h * iconSize2)
panel:SetZPos(999)
panel:InvalidateLayout(true)
panel:SetModel(model, skin, bodygroups)
panel:SetPos(self.slots[x][y]:GetPos())
panel.gridX = x
panel.gridY = y
if (advanced) then
local entity = panel:GetEntity()
color = color or Color(255, 255, 255)
if (color) then
panel:SetColor(color)
end
if (material) then
entity:SetMaterial(material)
end
if (skin) then
entity:SetSkin(skin)
end
if (OnInventoryDraw) then
OnInventoryDraw(item, entity)
end
panel.LayoutEntity = function(this, entity)
if (ix.gui.menu and IsValid(ix.gui.menu)) then
this:SetColor(ColorAlpha(color, ix.gui.menu:GetAlpha()))
end
if (!bRotate) then return end
local angle = entity:GetAngles()
angle.y = angle.y + FrameTime() * 30
entity:SetAngles(angle)
end
end
if (self:IsEquipSlotsPanel()) then
if self.slots[1] then
-- witness my error noia
local x1W = self.slots[1][1] and self.slots[1][1].GetWide and self.slots[1][1]:GetWide()
local x1Pos = self.slots[1][1] and self.slots[1][1].GetPos and self.slots[1][1]:GetPos()
local _, newY = false, false
if self.slots[1][y - 5] and self.slots[1][y - 5].GetPos then
_, newY = self.slots[1][y - 5]:GetPos()
end
if (y > 5 and x == 1) and (x1W and x1Pos and newY) then
panel:SetPos(x1Pos + (x1W * 4), newY)
end
end
end
panel.gridW = w
panel.gridH = h
local inventory = ix.item.inventories[self.invID]
if (!inventory) then
return
end
local itemTable = inventory:GetItemAt(panel.gridX, panel.gridY)
panel:SetInventoryID(inventory:GetID())
panel:SetItemTable(itemTable)
if (self.panels[itemTable:GetID()]) then
self.panels[itemTable:GetID()]:Remove()
end
if (advanced) then
if (itemTable.iconCam) then
panel:SetCamPos(itemTable.iconCam.pos)
panel:SetFOV(itemTable.iconCam.fov)
panel:SetLookAng(itemTable.iconCam.ang)
else
local entity = panel:GetEntity()
local pos = entity:GetPos()
local camData = PositionSpawnIcon(entity, pos)
if (camData) then
panel:SetCamPos(camData.origin)
panel:SetFOV(camData.fov)
panel:SetLookAng(camData.angles)
end
end
else
if (itemTable.exRender) then
panel.Icon:SetVisible(false)
panel.ExtraPaint = function(this, panelX, panelY)
local exIcon = ikon:GetIcon(itemTable.uniqueID)
if (exIcon) then
surface.SetMaterial(exIcon)
surface.SetDrawColor(color_white)
surface.DrawTexturedRect(0, 0, panelX, panelY)
else
ikon:renderIcon(
itemTable.uniqueID,
itemTable.width,
itemTable.height,
itemTable:GetModel(),
itemTable.iconCam
)
end
end
else
-- yeah..
RenderNewIcon(panel, itemTable)
end
end
panel.slots = {}
for i = 0, w - 1 do
for i2 = 0, h - 1 do
local slot = self.slots[x + i] and self.slots[x + i][y + i2]
if (IsValid(slot)) then
slot.item = panel
panel.slots[#panel.slots + 1] = slot
else
for _, v in ipairs(panel.slots) do
v.item = nil
end
panel:Remove()
return
end
end
end
return panel
end
end
function PANEL:ReceiveDrop(panels, bDropped, menuIndex, x, y)
local panel = panels[1]
if (!IsValid(panel)) then
self.previewPanel = nil
return
end
if (bDropped) then
local inventory = ix.item.inventories[self.invID]
if (inventory and panel.OnDrop) then
local dropX = math.ceil((x - 0 - (panel.gridW - 1) * 32) / self.iconSize)
local dropY = math.ceil((y - self:GetPadding(2) - (panel.gridH - 1) * 32) / self.iconSize)
panel:OnDrop(true, self, inventory, dropX, dropY)
end
self.previewPanel = nil
else
self.previewPanel = panel
self.previewX = x
self.previewY = y
end
end
function PANEL:CreateNoSlots(backpacks, type)
if backpacks.slots then
for _, v in pairs(backpacks.slots) do
if IsValid(v) then
v:Remove()
end
end
end
backpacks.slots = {}
if type == "noSlots" then return end
for x = 1, (!type and 7 or type == "noLarge" and 4 or 3) do
for y = 1, 4 do
local noSlot = backpacks:Add("Panel")
noSlot:SetPos((x - 1) * iconSize + (iconSize * self:GetNoSlotsXPosMultiplier(type)), (y - 1) * iconSize + SScaleMin(30 / 3))
noSlot:SetSize(iconSize, iconSize)
noSlot.Paint = PaintLockedSlot
backpacks.slots[#backpacks.slots + 1] = noSlot
end
end
end
function PANEL:UpdateNoSlots()
local backpacks = ix.gui.menuInventoryParent.backpacks
if !backpacks or backpacks and !IsValid(backpacks) then return end
local char = LocalPlayer():GetCharacter()
if !char then return end
local inventory = char:GetInventory()
if !inventory then return end
local hasSmallBag = inventory:HasItem("smallbag")
local hasLargeBag = inventory:HasItem("largebag")
local smallBag = hasSmallBag and self:GetIsInEquipSlots(char, hasSmallBag)
local largeBag = hasLargeBag and self:GetIsInEquipSlots(char, hasLargeBag)
if (!smallBag and !largeBag) then
self:CreateNoSlots(backpacks)
elseif largeBag and !smallBag then
self:CreateNoSlots(backpacks, "noSmall")
elseif !largeBag and smallBag then
self:CreateNoSlots(backpacks, "noLarge")
elseif largeBag and smallBag then
self:CreateNoSlots(backpacks, "noSlots")
end
end
function PANEL:GetIsInEquipSlots(char, item)
local eqSlots = char:GetEquipInventory()
if !eqSlots then return false end
if !item.invID then return false end
if item.invID != eqSlots then return false end
return true
end
function PANEL:GetNoSlotsXPosMultiplier(type)
return (!type and 0 or type == "noLarge" and 3 or 4)
end
vgui.Register("ixInventory", PANEL, "Panel")
hook.Add("CreateMenuButtons", "ixInventory", function(tabs)
if (hook.Run("CanPlayerViewInventory") == false) then
return
end
tabs["inv"] = {
bDefault = true,
RowNumber = 2,
Width = 19,
Height = 17,
Icon = "willardnetworks/tabmenu/navicons/inventory.png",
Create = function(info, tempCont)
local titlePushDown = SScaleMin(30 / 3)
local padding = SScaleMin(30 / 3)
local topPushDown = SScaleMin(150 / 3)
local scale780 = SScaleMin(780 / 3)
local scale120 = SScaleMin(120 / 3)
tempCont:SetSize(ScrW(), ScrH())
local newCont = tempCont:Add("Panel")
newCont:SetSize(ScrW() - (topPushDown * 2), scale120 + scale780 + titlePushDown)
newCont:Center()
local sizeXtitle, sizeYtitle = newCont:GetWide(), scale120
local sizeXcontent, sizeYcontent = newCont:GetWide(), (scale780)
newCont.titlePanel = newCont:Add("Panel")
newCont.titlePanel:SetSize(sizeXtitle, sizeYtitle)
newCont.titlePanel:SetPos(newCont:GetWide() * 0.5 - newCont.titlePanel:GetWide() * 0.5)
local invTitleIcon = newCont.titlePanel:Add("DImage")
invTitleIcon:SetImage("willardnetworks/tabmenu/navicons/inventory.png")
invTitleIcon:SetSize(SScaleMin(19 / 3), SScaleMin(17 / 3))
local invTitle = newCont.titlePanel:Add("DLabel")
invTitle:SetFont("TitlesFontNoClamp")
invTitle:SetText("Inventaire")
invTitle:SizeToContents()
invTitle:SetPos(SScaleMin(27 / 3), (SScaleMin(17 / 3) - invTitle:GetTall()) * 0.5)
newCont.contentFrame = newCont:Add("Panel")
newCont.contentFrame:SetSize(sizeXcontent, sizeYcontent)
newCont.contentFrame:SetPos(newCont:GetWide() * 0.5 - newCont.contentFrame:GetWide() * 0.5, titlePushDown)
newCont.invFrame = newCont.contentFrame:Add("Panel")
newCont.invFrame:SetSize(newCont.contentFrame:GetWide() * 0.5 - padding, newCont.contentFrame:GetTall())
newCont.invFrame:Dock(LEFT)
newCont.invFrame:DockMargin(0, 0, padding, 0)
newCont.backpacks = newCont.invFrame:Add("Panel")
newCont.backpacks:SetTall(((iconSize + SScaleMin(2 / 3)) * 4) + SScaleMin(21 / 3))
newCont.backpacks:Dock(BOTTOM)
ix.gui.menuInventoryParent = newCont
local canvas = newCont.invFrame:Add("DTileLayout")
local canvasLayout = canvas.PerformLayout
canvas.PerformLayout = nil -- we'll layout after we add the panels instead of each time one is added
canvas:SetBorder(0)
canvas:SetSpaceX(2)
canvas:SetSpaceY(2)
canvas:Dock(FILL)
ix.gui.menuInventorynewCont = canvas
local panel = canvas:Add("ixInventory")
panel.bNoBackgroundBlur = true
panel.childPanels = {}
local char = LocalPlayer():GetCharacter()
local inventory = char:GetInventory()
if (inventory) then
panel:SetInventory(inventory)
end
ix.gui.inv1 = panel
ix.gui.inv1:UpdateNoSlots()
local bFoundLarge, bFoundSmall = false, false
for _, v in SortedPairsByMemberValue(inventory:GetItemsByBase("base_containerbags", true), "id") do
if v.invID and char.GetEquipInventory and v.invID != char:GetEquipInventory() then continue end
if (!v.isBag) then
continue
end
if (v.name != "Sac" and v.name != "Petite sacoche") then
continue
elseif (v.name == "Sac") then
if (bFoundLarge) then
continue
else
bFoundLarge = true
end
elseif (v.name == "Petite sacoche") then
if (bFoundSmall) then
continue
else
bFoundSmall = true
end
end
v.functions.View.OnClick(v)
end
canvas.PerformLayout = canvasLayout
canvas:Layout()
newCont.charFrame = newCont.contentFrame:Add("CharFrame")
hook.Run("PostCharInfoFrameOpened", newCont.charFrame)
local backspaceTitleIcon = newCont.backpacks:Add("DImage")
backspaceTitleIcon:SetImage("willardnetworks/mainmenu/content.png")
backspaceTitleIcon:SetSize(SScaleMin(16 / 3), SScaleMin(16 / 3))
backspaceTitleIcon:SetPos(SScaleMin(1 / 3), SScaleMin(2 / 3))
local backspaceTitle = newCont.backpacks:Add("DLabel")
backspaceTitle:SetFont("SmallerTitleFontNoClamp")
backspaceTitle:SetText("Sac à dos")
backspaceTitle:SizeToContents()
backspaceTitle:SetPos(SScaleMin(25 / 3))
end
}
end)
hook.Add("PostRenderVGUI", "ixInvHelper", function()
local pnl = ix.gui.inv1
hook.Run("PostDrawInventory", pnl)
end)