So, I have attempted making large open world survival games numerous times over the past years, and well, they always end up turning into a huge mess of code that is hard to read and hard to build off of (somewhat unavoidably considering the sheer volume of game logic associated with building such a game). This is obviously because I am still not a very good programmer (and not the best problem solver), or at least not good enough to write clean code that other programmers can understand and that I can come back to and figure out quickly to continue building off of it.
Anyways, I have decided to start from the ground up again, programing the inventory system for my game first. Is there any way I can Refactor/Reformat/Rewrite any of this code to be cleaner, easier to interpret and more performance efficient?
print (script.Name.." Loaded.");
local Players = game:GetService("Players");
local UserInputServiceService = game:GetService("UserInputService");
local ReplicatedStorage = game:GetService("ReplicatedStorage");
local RunService = game:GetService("RunService");
local Player = Players.LocalPlayer
local PlayerGui = Player:WaitForChild("PlayerGui");
local PlayerMouse = Player:GetMouse()
local PrimaryInterface = PlayerGui:WaitForChild("PrimaryInterface");
local CursorDisplay = PrimaryInterface:WaitForChild("CursorDisplay")
local Inventory = PrimaryInterface:WaitForChild("Inventory");
local Items = Inventory:WaitForChild("Items");
local PrimaryInterfaceData = PrimaryInterface:WaitForChild("Data");
local UIClones = PrimaryInterfaceData:WaitForChild("UIClones")
local ToggleInventoryButton = PrimaryInterface:WaitForChild("ToggleButton");
local DescriptionDisplay = Inventory.Items:WaitForChild("DescriptionDisplay");
local ItemsHeldInInventory = PrimaryInterfaceData.InventoryData.ItemsHeldInInventory;
local Modules = ReplicatedStorage:WaitForChild("Modules");
local FunctionLibrary = require(Modules:WaitForChild("FunctionLibrary"))
local function AddToItemStack(Slot, SlotData, ItemData)
SlotData.Quantity.Value = SlotData.Quantity.Value + ItemData.Quantity.Value;
Slot.StackQuantityDisplay.Text = "x"..SlotData.Quantity.Value;
FunctionLibrary.DestroyObject(ItemData.Parent);
end
local function AddItemToSlot(Slot, SlotData, ItemData)
ItemsHeldInInventory.Value = ItemsHeldInInventory.Value + 1;
SlotData.ImageModel.Value = ItemData.ImageModel.Value;
SlotData.ItemName.Value = ItemData.ItemName.Value;
SlotData.ItemType.Value = ItemData.ItemType.Value;
SlotData.Nutrition.Value = ItemData.Nutrition.Value;
SlotData.Quantity.Value = ItemData.Quantity.Value;
SlotData.SlotHasItem.Value = true;
if ItemData.Stackable.Value == true
then
Slot.StackQuantityDisplay.Text = "x"..SlotData.Quantity.Value;
Slot.StackQuantityDisplay.Visible = true;
end
local ImageModelClone = ItemData.ImageModel:Clone()
ImageModelClone.Parent = Slot.Viewport;
FunctionLibrary.DestroyObject(ItemData.Parent);
end
local function CheckForSpaceInInventory(ItemData)
local Slot = Items:FindFirstChild("Slot"..ItemsHeldInInventory.Value + 1);
if Slot and Slot.SlotData.SlotHasItem.Value == false then
AddItemToSlot(Slot, Slot.SlotData, ItemData);
else
print("Not enough space in inventory");
end
end
local function CheckIfItemStacks(ItemData)
local FoundExistingStack = false;
if ItemData.Stackable.Value == true then
for _, Slot in ipairs(Items:GetChildren()) do
if Slot:IsA("ImageButton")
and Slot.SlotData.ItemName.Value == ItemData.ItemName.Value
and Slot.SlotData.SlotHasItem.Value == true
then
FoundExistingStack = true;
AddToItemStack(Slot, Slot.SlotData, ItemData);
else
-- check for space to store new item
CheckForSpaceInInventory(ItemData);
end
break
end
else
if ItemData.Stackable.Value == false then
CheckForSpaceInInventory(ItemData);
end
end
end
local function CheckItemType(ItemData)
if ItemData.ItemType.Value ~= "Tool" then
CheckIfItemStacks(ItemData)
end
end
local function PlayerClickedItem(Input)
if Input.UserInputType == Enum.UserInputType.MouseButton1
or Input.UserInputType == Enum.UserInputType.Touch
then
if PlayerMouse.Target then
local ItemData = PlayerMouse.Target:FindFirstChild("Item")
or PlayerMouse.Target.Parent:FindFirstChild("Item")
if ItemData then
CheckItemType(ItemData);
end
end
end
end
UserInputServiceService.InputBegan:Connect(PlayerClickedItem);
local function MouseHoverOverItem()
if PlayerMouse.Target
and PlayerMouse.Target:FindFirstChild("Item")
or PlayerMouse.Target
and PlayerMouse.Target.Parent:FindFirstChild("Item")
then
local ItemData = PlayerMouse.Target:FindFirstChild("Item") or PlayerMouse.Target.Parent:FindFirstChild("Item");
CursorDisplay.Position = UDim2.new(0, PlayerMouse.X + 25, 0, PlayerMouse.Y);
CursorDisplay.Text = ItemData:FindFirstChild("ItemName").Value;
CursorDisplay.Visible = true;
else
CursorDisplay.Visible = false;
end
end
PlayerMouse.Move:Connect(MouseHoverOverItem)
local function ToggleInventoryVisibility()
if Inventory.Visible == false then
Inventory.Visible = true
else if Inventory.Visible == true then
Inventory.Visible = false
Inventory.UIClones:ClearAllChildren()
-- remove ui menus
end
end
end
ToggleInventoryButton.MouseButton1Click:Connect(ToggleInventoryVisibility)
local function ToggleItemDescriptionDisplay(ItemName, Show)
if Show == true then
DescriptionDisplay.Visible = true;
DescriptionDisplay.Text = ItemName.Value;
else
DescriptionDisplay.Visible = false;
end
end
function ShowItemMenu(Slot, SlotData)
local UIClone = UIClones:FindFirstChild(SlotData.ItemType.Value.."UI"):Clone()
UIClone.Parent = Inventory.UIClones;
UIClone.Position = UDim2.new(0, PlayerMouse.X, 0, PlayerMouse.Y);
UIClone.Visible = true;
UIClone.SlotLink.Value = Slot;
end
local function InventoryInteractionController()
for _, v in ipairs(Inventory.Items:GetChildren()) do
if v:IsA("ImageButton")
then
v.MouseEnter:Connect(function()
local SlotData = v.SlotData;
if SlotData.SlotHasItem.Value == true then
ToggleItemDescriptionDisplay(SlotData.ItemName, true)
v.MouseLeave:Connect(function()
DescriptionDisplay.Visible = false;
end)
else
ToggleItemDescriptionDisplay(SlotData.ItemName, false)
end
end)
v.Activated:Connect(function()
local SlotData = v.SlotData;
if v.SlotData.SlotHasItem.Value == true
--if slot has an item
then
Inventory.UIClones:ClearAllChildren()
--remove other possible menus
ShowItemMenu(v, SlotData)
end
end)
end
end
end
InventoryInteractionController()