Will's Portfolio | Scripter


Hi there! I’m Will and I’ve been scripting on Roblox for 6 years and I’ve contributed to over 300 million visits. I’ve worked on various projects throughout the years, some of them are Super Blox Soccer, Quicksand 2, Raise a Child, and more! I’ve also learnt a little bit of other coding languages like C#, C++, C, and a bit of TypeScript. I have also learnt the usage of OOP and how important it can be to use some times and I also know how to effectively script and I know how to make scripts fairly optimized. Moreover, I also have prior experience with Knit, Rojo, and roblox-ts (typescript). I also tend to keep things organized while working on projects, that being using folders often, adding comments in my own code, using modules to make code more organized, etc.


I’ve contributed to multiple projects before, some big, some small. I’ve also scripted personal projects and events for youtubers. The projects I mainly work on in my free time is usually battleground games or other stuff that I find interesting. Anyways, below is some of my previous work as well as some videos of them.

Here are the games I've worked on in the past/currently

Quicksand 1 - First quicksand game which was discontinued because we decided to work on the 2nd game.

Quicksand 2 - Second quicksand game which has on average about 100-300 players and over 13k members. (The owner was scammed and their group was hacked and we no longer have access to the game)

Absolute Driving - A game about driving around and earning money. I helped pushed updates to improve the game with the owner.

Hot Potato - A game about passing around a potato before it explodes. I am the only scripter and my friend is the owner, never finished it fully but will probably finish it soon. The game includes destruction physics, round system, passing around a hot potato, and more.

Russian Sleep Experiment (Got banned and the group was locked)

Mup Studios -Over 100k members and I’ve worked on events for the owner and their YouTube channel. Also worked on games with them that are released and that you can play right now: Raise A Child which is a game where you raise a baby and you have to prevent it from getting killed by other players or entities. I had a lot of fun working on this and I got to work on several updates for the game.

A.C.E Group - The group for the A.C.E border game, over 10k members.

Shared Visions -A 2 player obby which sadly failed. (Same owner as with quicksand 2 and the game was also hacked)

Hats RNG - An RNG game I made for fun with my friends.

Archkos Studios - A game development studio I worked with but I quit after I lost motivation for the game I was working on with them. I had a lot of fun working on the game while I had the motivation for it and I learned quite a bit of new skills.

Personal projects

Most of them aren’t completed but they show some of my scripting knowledge.

Car Suspension Test - A game I made where I learned on how to make cars with functioning suspension.

Chaos RNG - A RNG game with random events that can happen. (Made it in like 5 hours so it’s nothing special)

Battlegrounds Game - A battleground game that I made for testing my skills and trying to improve on combat and how dashing works in these games. I learned a lot from this project and how to make certain systems.

tycoon but only one path - A tycoon game where there’s only one conveyer belt and it goes up every story of the building. Also a learning experience for the most part and it helped me understand how tycoons are made and how to save data more efficiently.

destroy things and stuff - A game where you destroy buildings and earn coins off of it and then you can progress through the game and earn more tools and stuff. Unfinished project but I learned a lot, for example I learned how to use the new “GeometryService” API.

There are so many more games that I have made but they are incomplete that it’s not even worth showing you them. However, if you want to see more games contact me and I can show more stuff that I made.

Some videos of my work

The Fog Is Coming

Youtube Video (This is the YouTuber who I’ve worked with, I helped make events such as this one where you have to survive. I scripted the doors, hunger system, the spawning menu, and some other small stuff such as the guns.

Raise a Child

Streamable video

Ace Border

Streamable video

Quicksand 2

Streamable video

Code Snippets

An OOP car module I made for my “Line Simulator” game.

local Car = {}
Car.__index = Car

--Services
local TweenService = game:GetService("TweenService")

--Folders
local Map = workspace.Map
local Cars = Map.Cars
local Points = Cars.Points

--Functions
function Car.new(Speed, CarModel : Model)
	local Clone = CarModel:Clone()
	Clone.Parent = Cars
	
	local RandomPoint = math.random(1,2)
	local RandomEnd = nil
	if RandomPoint == 1 then
		RandomPoint = Points.Spawn1
		RandomEnd = Points.End1
	else
		RandomPoint = Points.Spawn2
		RandomEnd = Points.End2
	end
	
	return setmetatable({CarModel = Clone; StartPoint = RandomPoint; EndPoint = RandomEnd; Speed = Speed;}, Car)
end

function Car:Start()
	--Variables
	local CarModel : Model = self.CarModel
	local StartPoint : Part = self.StartPoint
	local EndPoint : Part = self.EndPoint
	local Speed : number = self.Speed
	
	--Pivot the car to the point
	CarModel:PivotTo(StartPoint.CFrame)
	CarModel.PrimaryPart.CFrame = CFrame.lookAt(CarModel.PrimaryPart.Position, EndPoint.Position)
	
	--Sound
	local EngineIdle = script["Engine Idle"]:Clone()
	EngineIdle.Parent = CarModel.PrimaryPart
	EngineIdle:Play()
	
	--Move the car
	CarModel:TranslateBy(EndPoint.Position)
	task.wait(Speed)
	
	--Destroy the car
	CarModel:Destroy()
	
	--Destroy the meta table
	setmetatable(self, nil)
end

return Car

This is a LineModule I made using OOP for the same game as the one above.

local Line = {}
Line.__index = Line

--Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

--Folders
local Remotes = ReplicatedStorage.Remotes
local PathFolder = workspace.Map.Path

--Remotes
local Notify = Remotes.Notify

--Tables
local PlayerLines = {}

--Line stats
local LineStats = {}

for i = 50, 1, -1 do
	local baseCash = 250 * (51 - i) ^ 2 -- Increases exponentially based on line number
	local baseCost = 3000 * (51 - i) ^ 2 -- Same for cost, scaling similarly

	LineStats[i] = {
		CashPerSecond = math.random(baseCash, baseCash + 500),
		CostToMoveUp = math.random(baseCost, baseCost + 20000),
	}
end

--Functions
function Line.GetCashPerSecond(Player)
	local playerPos = Line.GetCurrentPositionInLine(Player)
	local lineStatPos = LineStats[playerPos]
	if not lineStatPos then warn("No line stat pos") return nil end
	
	return lineStatPos.CashPerSecond
end

function Line.newPlayer(Player : Player) --Initiates a new player
	local metaTable = setmetatable({Player = Player; PlayerData = Player.PlayerData; PlaceInLine = Player.PlayerData.PlaceInLine; CashPerSecond = Player.PlayerData.CashPerSecond;}, Line)
	table.insert(PlayerLines, metaTable)
	
	return metaTable
end

function Line.getPlayer(Player : Player)
	for i, v in PlayerLines do
		if v.Player.Name == Player.Name then
			return v
		end
	end
	
	return Line.newPlayer(Player)
end

function Line.GetCurrentPositionInLine(Player)
	return tonumber(Player.PlayerData:FindFirstChild("PlaceInLine").Value.Name)
end

function Line.Move(Player, Position)
	--Get the player character and humanoid and HRP (humanoidrootpart)
	local Character = Player.Character or Player.CharacterAdded:Wait()
	local Humanoid : Humanoid = Character:FindFirstChild("Humanoid")
	local HRP = Character:FindFirstChild("HumanoidRootPart")

	local newMoveValue = Instance.new("Vector3Value", Player.PlayerData.OrderToMoveIn)
	newMoveValue.Name = tostring(#Player.PlayerData.OrderToMoveIn:GetChildren())
	newMoveValue.Value = Position
	
	if Player:GetAttribute("Moving") == true then
		repeat task.wait() until Player:GetAttribute("Moving") == false
	end

	local positionToWalkTo
	local closest
	if #Player.PlayerData.OrderToMoveIn:GetChildren() > 1 then
		for i, v in Player.PlayerData.OrderToMoveIn:GetChildren() do
			if closest == nil then
				closest = v.Name
				positionToWalkTo = v.Value
			elseif tonumber(closest) > tonumber(v.Name) then
				closest = v.Name
				positionToWalkTo = v.Value
			end
		end
	else
		positionToWalkTo = Position
	end
	
	Player:SetAttribute("Moving", true)
	
	repeat task.wait()
		Humanoid:MoveTo(positionToWalkTo)
	until (HRP.Position - positionToWalkTo).Magnitude <= 3
	
	newMoveValue:Destroy()
	
	Player:SetAttribute("Moving", false)
end

function Line.IsPositionOccupied(Player : Player, Position)
	for i, v in Players:GetPlayers() do
		if v:FindFirstChild("PlayerData") then
			if tonumber(v.PlayerData.PlaceInLine.Value.Name) == Position and v.UserId ~= Player.UserId then
				return v
			end
		end
	end
	
	return nil
end

function Line.GetNextPlaceInLine(Position)
	local object = PathFolder:FindFirstChild(Position - 1)
	if not object then warn("Object not found") return nil end
	
	return object
end

function Line.GetCostForNextPlace(Player)
	local placeInTable = LineStats[tonumber(Player.PlayerData.PlaceInLine.Value.Name)]
	if not placeInTable then return warn("Place in table not found") end
	
	return placeInTable.CostToMoveUp
end

function Line:MoveToSpecificSpot(posInLine)
	local placeInLineObject = PathFolder[posInLine]
	if not placeInLineObject then return warn("Can't go over 50 nor under 1") end
	
	self.PlaceInLine.Value = placeInLineObject
	
	local playerOccupyingPosition = Line.IsPositionOccupied(self.Player, Line.GetCurrentPositionInLine(self.Player))
	if playerOccupyingPosition then
		Line.getPlayer(playerOccupyingPosition):MoveUp()
	end
	
	Line.Move(self.Player, placeInLineObject.Position)
end

function Line:MoveToCurrent()
	local posInLine = Line.GetCurrentPositionInLine(self.Player)
	local object = PathFolder:FindFirstChild(posInLine)
	if not object then return warn("No object") end
	
	for i, v in Players:GetPlayers() do
		if tonumber(v.PlayerData.PlaceInLine.Value.Name) == posInLine and v.UserId ~= self.Player.UserId then
			local newMeta = Line.getPlayer(v)
			newMeta:MoveUp()
		end
	end
	
	Line.Move(self.Player, object.Position)
end

function Line:MoveUp() --Moves the player 1 step above (if they're not already in 1st place)
	local posInLine = Line.GetCurrentPositionInLine(self.Player)
	if posInLine > 1 then
		--Place in line
		local nextPlaceInLine = posInLine-1
		local nextPlaceInLineObject = PathFolder[nextPlaceInLine]
		if not nextPlaceInLineObject then return warn("Did not find line object") end
		
		--Change the current place in line
		self.PlaceInLine.Value = nextPlaceInLineObject
		
		Line.Move(self.Player, nextPlaceInLineObject.Position)
	else
		--Notify the player that they can't advance anymore
		Remotes.Notify:FireClient(self.Player, "Error", "You are 1st place, can't advance in line!", 2)
	end
end

function Line:MoveDown()
	local posInLine = Line.GetCurrentPositionInLine(self.Player)
	if posInLine < 50 then
		--Place in line
		local previousPlaceInLine = posInLine+1
		local previousPlaceInLineObject = PathFolder:FindFirstChild(previousPlaceInLine)
		
		--Change the current place in line
		self.PlaceInLine.Value = previousPlaceInLineObject
		
		--Move the player
		Line.Move(self.Player, previousPlaceInLineObject.Position)
		return true
	else
		print("Cant move down")
		return false
	end
end

return Line

A combat module I made for my battlegrounds game, it does not use OOP since I couldn’t really find a use case for it. It uses other modules I made myself too in order to work which is why you can see stuff such as “AnimationModule”. This script also utilizes state machines which I something I recently discovered.

local CombatMod = {}

--Services
local Players = game:GetService("Players")
local SSS = game:GetService("ServerScriptService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")

--Folders
local Modules = SSS.Modules
local ScriptsFolder = SSS.Scripts
local States = ScriptsFolder.States
local Animations = SSS.Animations
local Remotes = ReplicatedStorage.Remotes
local Libraries = SSS.Libraries
local SoundsFolder = ReplicatedStorage.Sounds

--Modules
local PlayerState = require(Modules.PlayerState)
local HitboxModule = require(Modules.Hitbox)
local AnimationModule = require(Modules.AnimationModule)
local SoundModule = require(Modules.Sound)
local VoxBreaker = require(Libraries.VoxBreaker2)

--Tables
local Settings = {
	--M1
	M1_Damage = 3;
	M1_Speed = 0.4;
	LastM1_Speed = 1;
	M1_Hitbox = Vector3.new(6,6,6);
	
	--Ragdoll
	Ragdoll_Time = 1.5;
	
	--Stun
	Stun_Time = 1;
}

function CombatMod.CanPunch(Player)
	--Checking if it's an npc, if they have a stun folder, and if they're dead or not
	local Stuns
	if Player:IsA("Player") then
		Stuns = Player.Character:FindFirstChild("Stuns")
		
		if Player.Character:FindFirstChild("Humanoid").Health <= 0 then
			return false
		end
	else
		Stuns = Player:FindFirstChild("Stuns")
		
		if Player:FindFirstChild("Humanoid").Health <= 0 then
			return false
		end
	end
	
	if #Stuns:GetChildren() > 0 then return false end
	
	--Player initation stuff
	local playerSM = PlayerState.GetStateMachine(Player)
	if playerSM._CurrentState == "Idle" then -- or playerSM._CurrentState == "Attacking"
		return true
	else
		return false
	end
end

function CombatMod.isAPlayer(Player)
	local PlayerData
	local M1
	local Character
	local HRP
	local CF
	
	if Player:IsA("Player") then
		PlayerData = Player.PlayerData
		M1 = PlayerData.M1
		Character = Player.Character or Player.CharacterAdded:Wait()
		HRP = Character:FindFirstChild("HumanoidRootPart")
		CF = Remotes.GetPos:InvokeClient(Player, HRP)
	else
		local plrDataFolder
		if not Player:FindFirstChild("PlayerData") then
			plrDataFolder = Instance.new("Folder", Player)
			plrDataFolder.Name = "PlayerData"

			local m1 = Instance.new("IntConstrainedValue", plrDataFolder)
			m1.Name = "M1"
			m1.MinValue = 1
			m1.MaxValue = 4
			m1.Value = 1

			local IFrame = Instance.new("BoolValue", plrDataFolder)
			IFrame.Name = "IFrames"

			local State = Instance.new("StringValue", plrDataFolder)
			State.Name = "State"
			State.Value = "Idle"
		else
			plrDataFolder = Player:FindFirstChild("PlayerData")
		end

		PlayerData = plrDataFolder
		M1 = plrDataFolder.M1
		Character = Player
		HRP = Player.HumanoidRootPart
		CF = HRP.CFrame
	end
	
	return PlayerData, M1, Character, HRP, CF
end

function CombatMod.M1(Player : Player)
	--Player initation stuff and checking if the player can even punch
	if CombatMod.CanPunch(Player) == false then return end
	
	--Player state machine
	local playerSM = PlayerState.GetStateMachine(Player)
	
	--Changing State (VERY IMPORTANT THAT IT'S HERE OTHERWISE IT MIGHT TAKE TOO LONG TO CHANGE STATE WHICH WILL MAKE IT SO YOU CAN M1 TWICE IN A ROW)
	playerSM:ChangeState("Attacking")
	
	--Player variables
	local PlayerData, M1, Character, HRP, CF = CombatMod.isAPlayer(Player)
	
	--Normal Variables
	local TimeToWait = Settings.M1_Speed

	--If the m1 is more than 4 then reset it to 1
	if M1.Value >= 4 then
		M1.Value = 1
	else --else add a m1 value
		--Adding m1 value
		M1.Value += 1
		
		--Check if the m1 is 4 or higher (cant be higher but incase it bugs) (THIS IS FOR DESTRUCITON, REMAKING IT LATER MAYBE)
		--if M1.Value >= 4 then
		--	--Create a voxelbreaker hitbox
		--	--local Voxels = VoxBreaker:CreateHitbox(Settings.M1_Hitbox, CF * CFrame.new(0,0,-3), Enum.PartType.Block, 4, 30)
		--	local Voxels = VoxBreaker:CreateHitbox(Settings.M1_Hitbox, CF * CFrame.new(0,0,-3), Enum.PartType.Block, 4, 30)
		--	for i, v in Voxels do
		--		v.Anchored = false
		--		v:ApplyImpulse(Character.HumanoidRootPart.CFrame.LookVector*250)
		--	end
		--end
	end
	
	--print(M1.Value)
	
	--Trail
	if Character["Right Arm"]:FindFirstChild("Trail") and Character["Left Arm"]:FindFirstChild("Trail") then
		Character["Right Arm"].Trail.Enabled = true
		Character["Left Arm"].Trail.Enabled = true
	end
	
	--Animation
	AnimationModule.PlayAnimation(Player, Animations.M1s[M1.Value])
	--The amount of time it takes for an m1 to finish, making it more realistic (scrapped, made the sound not play some times and js really buggy)
	
	--Hitbox stuff
	local newHitbox = HitboxModule.new(Settings.M1_Hitbox, CF * CFrame.new(0,0,-3), Character, nil, false)
	local targets = newHitbox:GetTargets()
	local amountOfTargetsBlocking = {}
	if targets and #targets > 0 then
		if M1.Value >= 4 then
			TimeToWait += 0.5
		end
		
		for _, targetChr : Model in targets do
			local targetHRP = targetChr:FindFirstChild("HumanoidRootPart")
			if not targetHRP then continue end
			
			--Get the humanoid
			local TargetHumanoid = targetChr:FindFirstChild("Humanoid")
			if not TargetHumanoid then
				continue
			end
			
			local newSound = SoundModule.new(SoundsFolder.Punch, targetChr.HumanoidRootPart, true)
			newSound:AddPitchEffect(Random.new():NextNumber(0.9,1.1))
			
			local targetSM = PlayerState.GetStateMachine(targetChr)
			if targetSM and targetSM:GetCurrentState() == "Block" then
				local displacementVector: Vector3 = targetHRP.Position - HRP.Position
				local direction: Vector3 = displacementVector.Unit
				local angle: number = math.acos(targetHRP.CFrame.LookVector:Dot(direction))
				if angle >= math.rad(90) then
					--Print for debugging
					print("blocked")
					
					--Take damage
					TargetHumanoid:TakeDamage(1)
					
					--Add a muffled sound effect and play the sound
					newSound:AddMuffledEffect()
					newSound:Play()
					
					--Add the target to the AOTB so if all targets are blocking the last m1 gets delayed
					table.insert(amountOfTargetsBlocking, targetChr)
					
					--Continue the table
					continue
				else
					print("not blocked")
				end
			end
			
			--Take damage
			TargetHumanoid:TakeDamage(Settings.M1_Damage)
			
			--Give the player a highlight, cool effects
			local Highlight = script.Highlight:Clone()
			Highlight.Parent = targetChr
			Highlight.Adornee = targetChr
			
			--Play the effect
			TweenService:Create(Highlight, TweenInfo.new(0.5), {FillTransparency = 1}):Play()
			task.delay(0.5, function()
				Highlight:Destroy()
			end)
			
			--Check if the target is a player
			local targetPlayer = Players:GetPlayerFromCharacter(targetChr)
			
			--Get the statemachine
			local stateMC = PlayerState.GetStateMachine(targetPlayer or targetChr) --statemachine
			stateMC:ChangeState("Stunned")
			
			--Add stun
			local newStun = Instance.new("StringValue", targetChr:FindFirstChild("Stuns"))
			newStun.Name = "Stun"
			
			--Unstun the target if they're not stunned again
			task.delay(Settings.Stun_Time, function()
				newStun:Destroy()
				
				if #targetChr:FindFirstChild("Stuns"):GetChildren() <= 0 then
					stateMC:ChangeState("Idle")
				end
			end)
			
			--Check if the m1 is over 4 and if it is then ragdoll the target
			if M1.Value >= 4 then
				--Change the state to ragdoll
				stateMC:ChangeState("Ragdoll")
				
				--Wait a couple of seconds before unragdolling
				task.delay(Settings.Ragdoll_Time, function()
					stateMC:ChangeState("Idle")
				end)
			end
			
			--Play sound
			newSound:Play()
			
			--Force to apply
			local forceToApply = HRP.CFrame.LookVector*700
			
			--Add force to the target
			local targetPlayer = Players:GetPlayerFromCharacter(targetChr)
			if targetPlayer then
				Remotes.ApplyImpulse:FireClient(targetPlayer, forceToApply)
			else
				targetChr.HumanoidRootPart:ApplyImpulse(forceToApply)
			end
		end
	elseif not targets or #targets <= 0 then
		if M1.Value >= 4 or M1.Value >= 4 and #targets == #amountOfTargetsBlocking then
			--print("missed last m1")
			TimeToWait = Settings.LastM1_Speed
		end
		
		local newMissSound = SoundModule.new(SoundsFolder.Miss, HRP, true)
		newMissSound:AddPitchEffect(Random.new():NextNumber(0.8,1.2))
		newMissSound:Play()
	end
	
	--Destroying the hitbox
	newHitbox:Destroy(0.5)

	task.wait(TimeToWait)
	
	--Change the state to idle
	playerSM:ChangeState("Idle")
	
	--Disable the right arm trail
	if Character["Right Arm"]:FindFirstChild("Trail") and Character["Left Arm"]:FindFirstChild("Trail") then
		Character["Right Arm"].Trail.Enabled = false
		Character["Left Arm"].Trail.Enabled = false
	end
end

return CombatMod

This is an OOP module I made for a game that had items in it. It features stats of the items, easy to access functions that are easy to understand, and more.

local ItemMod = {}
ItemMod.__index = ItemMod

--Services--
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--Folders--
local Tools = ServerStorage.Tools
local Remotes = ReplicatedStorage.Remotes

--Tables--
local ItemsTable = {
	["Rocket Launcher"] = {
		Price = 1000; --The price for the item
		UseTime = 600; --The amount of seconds they get to keep the item
		GamepassID = 0; --Gamepass ID
		Description = "A rocket launcher that fires rockets"; --Description of the tool
		Model = Tools["Rocket Launcher"]; --The model of the item
	};
	
	["Stun Gun"] = {
		Price = 500; --The price for the item
		UseTime = 300; --The amount of seconds they get to keep the item
		GamepassID = 0; --Gamepass ID
		Description = "A stun gun that stuns enemies for a short period of time"; --Description of the tool
		Model = Tools["Stun Gun"]; --The model of the item
	};
	
	["Flaming Sword"] = {
		Price = 1500; --The price for the item
		UseTime = 900; --The amount of seconds they get to keep the item
		GamepassID = 0; --Gamepass ID
		Description = "A flaming sword with good range"; --Description of the tool
		Model = Tools["Flaming Sword"]; --The model of the item
	};
	
	["Ice Cube"] = {
		Price = 30; --The price for the item
		UseTime = 0; --The amount of seconds they get to keep the item
		OneTimeUse = true; --If its a one time use no timer is started
		GamepassID = 0; --Gamepass ID
		Description = "An ice cube that you can throw on the ground to slow down enemies"; --Description of the tool
		Model = Tools["Ice Cube"]; --The model of the item
	};
	
	["Spring"] = {
		Price = 500; --The price for the item
		UseTime = 300; --The amount of seconds they get to keep the item
		GamepassID = 0; --Gamepass ID
		Description = "A spring that makes you jump higher"; --Description of the tool
		Model = Tools["Spring"]; --The model of the item
	};
	
	["BoomBox"] = {
		Price = 500; --The price for the item
		UseTime = 300; --The amount of seconds they get to keep the item
		GamepassID = 0; --Gamepass ID
		Description = "Gives you a boombox tool where you can play music"; --Description of the tool
		Model = Tools["Spring"]; --The model of the item
	};
	
	["Wings"] = {
		Price = 3000; --The price for the item
		UseTime = 500; -- (maybe ignore rest)IF YOU CHANGE THIS REMEMBER TO CHANGE IT IN THE "RemoteHandler" SCRIPT AT LINE 311
		GamepassID = 0; --Gamepass ID
		Description = "Gives you the ability to fly"; --Description of the tool
		Model = Tools["Wings"]; --The model of the item
	};
}

function ItemMod.new(Player: Player, ItemName : string)
	local self = setmetatable({}, ItemMod)
	
	local itemInTable = ItemsTable[ItemName]
	if itemInTable then
		self.ItemInTable = itemInTable
		self.ItemName = itemInTable.Model.Name
		self.CloneOfModel = itemInTable.Model:Clone()
		self.Player = Player
		self.UseTime = itemInTable.UseTime
	else
		warn("No item in table")
		return nil
	end
	
	return self
end

function ItemMod.GetItemInfo(ItemName)
	warn("ITEM NAME: "..ItemName)
	local itemInTable = ItemsTable[ItemName]
	if not itemInTable then warn("No item in table bro") return nil end
	
	print("found item in table")
	return ItemsTable[ItemName]
end

function ItemMod:Purchase()
	if self.Player.Backpack:FindFirstChild(self.ItemName) or self.Player.StarterGear:FindFirstChild(self.ItemName) or self.Player.Character:FindFirstChild(self.ItemName) then
		Remotes.Notify:FireClient(self.Player, "ERROR", "You already have this item in your inventory!", 5)
		return warn("Already has weapon")
	end
	
	local price = self.ItemInTable.Price
	if self.Player.leaderstats.Coins.Value < price then
		warn("brokie")
		return false
	end
	
	warn("Purchasing item...")
	self.Player.leaderstats.Coins.Value -= price
	warn("Purchased!")
	
	Remotes.Notify:FireClient(self.Player, "SUCCESS", "Successfully bought "..self.ItemName.."!")
	
	return true
end

function ItemMod:GiveItem(startTimer)
	if self.Player.Backpack:FindFirstChild(self.CloneOfModel.Name) then
		
		return warn("Player already has tool") 
	end
	local cloneOfModel = self.CloneOfModel
	local player = self.Player
	cloneOfModel.Parent = player.Backpack
	
	if self.ItemInTable.OneTimeUse == false or not self.ItemInTable.OneTimeUse then
		self.NewCloneOfModel = cloneOfModel:Clone()
		self.NewCloneOfModel.Parent = player.StarterGear
	end
	
	if startTimer == true and (self.ItemInTable.OneTimeUse == false or not self.ItemInTable.OneTimeUse) then
		local newString = Instance.new("StringValue", player.PlayerData.Tools)
		newString.Name = cloneOfModel.Name
		
		for i = self.UseTime, 0, -1 do
			cloneOfModel.ToolTip = "Can be used for "..tostring(i).." more seconds"
			task.wait(1)
		end
		
		if cloneOfModel.Name == "Wings" then
			local alignPosition = self.Player.Character:FindFirstChildWhichIsA("AlignPosition", true)
			if alignPosition then
				alignPosition:Destroy()
			end
			
			for i, v in self.Player.Character:GetChildren() do
				if v:IsA("Accessory") and v:HasTag("Wings") then
					v:Destroy()
					break
				end
			end
		end
		
		cloneOfModel:Destroy()
		self.NewCloneOfModel:Destroy()
	elseif self.ItemInTable.OneTimeUse == true then
		print("one time use")
	end
end

function ItemMod:RemoveItem()
	local itemInBackpack = self.Player:FindFirstChild(self.CloneOfModel.Name)
	if itemInBackpack then
		itemInBackpack:Destroy()
	end
end

function ItemMod:Destroy()
	return setmetatable(nil, ItemMod)
end

return ItemMod

I’m available to work for around 2-6 hours a day and on the weekend 2-8 hours a day. Some days it could less because of exams or just personal stuff but most often you’re gonna find me working 2-6 hours a day.


I can negotiate prices and I accept hourly, per task, and upfront. I do not do upon completion payment. I prefer robux in payment but I can do USD too if it’s only really necessary.


You can contact me here on the Developer Forum or via Discord, my user is vtxe.


Thanks for reading, feel free to ask any questions.

Hello got very interest but here is saying i cant add you at discord you need to add me,you might need to change it at your discord configuration.

I got an offer too.