BackgroundHello there! π I have been on this platform since 2009 and since then have had a passion for developing. I am currently pursuing a degree in Computer Science! |
SkillsetI am a full stack engineer with a focus in gameplay systems and UX design. I also have skills in web development, as well as 3D modeling and graphic design. |
ExperienceI am currently employed at Sawhorse Interactive, and have had amazing opportunities to work with some of the biggest groups on Roblox! |
RECENT WORK
Chainsaw ManAs the lead developer for this project, I wanted to make something that was better than the other anime-based games on Roblox! I enjoyed working on the UI as well as the combat system on this project. |
MY WORK
Building Examples
Note that most of these building examples are extremely outdated!
Scripting Examples
Have experience with collaborative resources such as Rojo and frameworks such as Knit.
Backend for Round System
--[[
Round.lua
eliphant
Created on 12/03/2022 @ 17:28
Description:
No description provided.
Documentation:
No documentation provided.
--]]
--= Root =--
local Round = { _Priority = 1 }
--= Roblox Services =--
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local Players = game:GetService('Players')
local RunService = game:GetService('RunService')
--= Dependencies =--
local OddsHandler = shared("OddsHandler")
local VotingHandler = shared("VotingHandler")
local Signal = shared("Signal")
local Maid = shared("Maid")
local GetRemoteEvent = shared("GetRemoteEvent")
local GetRemoteFunction = shared("GetRemoteFunction")
--= Object References =--
local NotificationEvent = GetRemoteEvent("NotificationEvent")
local AddCoinEvent = GetRemoteEvent('AddCoinEvent')
local RemoveCoinEvent = GetRemoteEvent('RemoveCoinEvent')
local LightEvent = GetRemoteEvent("LightEvent")
local Assets = ReplicatedStorage:WaitForChild("Assets")
local ClockEnd = Signal.new()
local RoundEnd = Signal.new()
local ClockMaid = Maid.new()
local MapFolder
--= Constants =--
local KILLER_SELECTION = 10
local VOTING_TIME = 10
local INTERMISSION_TIME = 10
local ROUND_TIME = 20
local MAP_LOAD_TIME = 5
--= Variables =--
local RandomObj = Random.new()
local CurrentNotification = {}
--= Internal Functions =--
function _selectKiller() : Player
local weightedTable = OddsHandler:ReturnWeightedTable()
local killer = weightedTable[RandomObj:NextInteger(1, #weightedTable)]
return killer
end
function _resetPlayers() : nil
for _, player in pairs(Players:GetPlayers()) do
player:LoadCharacter()
end
end
function _spawnPlayers(PlayerTable : {}, Spawns : {}) : nil
for _, data in pairs(PlayerTable) do
local selectedSpawn = Spawns[RandomObj:NextInteger(1, #Spawns)]
data.Player.Character:PivotTo(selectedSpawn.CFrame * CFrame.new(0, 3, 0))
end
end
function _startClock(Time : number) : nil
if ClockMaid then
ClockMaid:Destroy()
end
ClockMaid = Maid.new()
local startTime = os.clock()
ClockMaid:GiveTask(RunService.Heartbeat:Connect(function()
if os.clock() - startTime >= Time then
ClockEnd:Fire()
end
end))
end
--= API Functions =--
function Round:Intermission() : nil
-- Start the round intermission
_startClock(INTERMISSION_TIME)
NotificationEvent:FireAllClients(INTERMISSION_TIME, "Intermission", "Intermission")
CurrentNotification = {INTERMISSION_TIME, "Intermission", os.clock()}
ClockEnd:Wait()
-- Start voting for the map
Round:Vote()
ClockEnd:Wait()
local selectedMap = Round:SelectMap()
-- Load the map
local mapInstance = Round:LoadMap(selectedMap)
-- Spawn coins on the map
AddCoinEvent:FireAllClients(mapInstance.CoinNodes:GetChildren(), "COINS")
_startClock(MAP_LOAD_TIME)
NotificationEvent:FireAllClients(MAP_LOAD_TIME, "Loading Map : " .. mapInstance.Name)
CurrentNotification = {MAP_LOAD_TIME, "Loading Map : " .. mapInstance.Name, os.clock()}
ClockEnd:Wait()
Round:Start(ROUND_TIME, mapInstance)
end
function Round:SelectMap() : string
return VotingHandler:CollectVotes()
end
function Round:LoadMap(mapName : string) : Instance
local map = Assets:WaitForChild("Maps"):WaitForChild(mapName):Clone()
map.Parent = MapFolder
return map
end
function Round:Vote() : nil
VotingHandler:StartVote()
_startClock(VOTING_TIME)
NotificationEvent:FireAllClients(VOTING_TIME, "Voting for Map")
CurrentNotification = {VOTING_TIME, "Voting for Map", os.clock()}
end
function Round:UnloadMap() : nil
MapFolder:ClearAllChildren()
end
function Round:WinCondition() : nil
ClockEnd:Fire()
end
function Round:LightsOut(Map : Instance)
local Lights = Map:WaitForChild("Lights")
local LightTable = { }
local LightPartTable = { }
for _, light in pairs(Lights:GetDescendants()) do
if light:IsA("PointLight") or light:IsA("SpotLight") or light:IsA("SurfaceLight") then
table.insert(LightTable, light)
elseif light:IsA("BasePart") and light.Material == Enum.Material.Neon then
table.insert(LightPartTable, light)
end
end
LightEvent:FireAllClients("Start")
for _ = 1, 5 do
for _, light in pairs(LightTable) do
light.Enabled = false
end
for _, light in pairs(LightPartTable) do
light.Transparency = 0
end
task.wait(0.1)
for _, light in pairs(LightTable) do
light.Enabled = true
end
for _, light in pairs(LightPartTable) do
light.Transparency = 0
end
task.wait(0.1)
end
LightEvent:FireAllClients("End")
for _, light in pairs(LightTable) do
light.Enabled = false
end
for _, light in pairs(LightPartTable) do
light.Transparency = 1
end
end
function Round:Start(RoundTime : number, Map : Instance) : nil
-- Start the round by spawning players
_spawnPlayers(_G.PlayerTable, Map:WaitForChild("Spawns"):GetChildren())
--Select the killer
_startClock(KILLER_SELECTION)
NotificationEvent:FireAllClients(KILLER_SELECTION, "Selecting Killer", "Round")
CurrentNotification = {KILLER_SELECTION, "Selecting Killer", os.clock()}
ClockEnd:Wait()
local killer = _selectKiller()
Round:LightsOut(Map)
-- Start the main round timer
_startClock(RoundTime)
NotificationEvent:FireAllClients(RoundTime, "Round")
CurrentNotification = {RoundTime, "Round", os.clock()}
ClockEnd:Wait()
RoundEnd:Fire()
end
RoundEnd:Connect(function()
_resetPlayers()
if ClockMaid then
ClockMaid:Destroy()
end
RemoveCoinEvent:FireAllClients()
Round:UnloadMap()
Round:Run()
end)
--= Initializers =--
function Round:Run() : nil
Round:Intermission()
end
function Round:Init() : nil
MapFolder = Instance.new("Folder")
MapFolder.Name = "CurrentMap"
MapFolder.Parent = workspace
Players.PlayerAdded:Connect(function(player)
if CurrentNotification[1] then
local delta = math.floor(os.clock() - CurrentNotification[3])
NotificationEvent:FireClient(player, CurrentNotification[1] - delta, CurrentNotification[2])
end
end)
end
--= Return Module =--
return Round
Module for Notification UI
--[[
NotificationPane.lua
eliphant
Created on 11/17/2022 @ 03:20
Description:
No description provided.
Documentation:
No documentation provided.
--]]
--= Roblox Services =--
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local Players = game:GetService('Players')
local RunService = game:GetService('RunService')
--= Dependencies =--
local UtilFunctions = shared('UtilFunctions')
local BasicPane = shared('BasicPane')
local GuiTemplates = shared('GuiTemplates')
local AnimNation = shared('AnimNation')
local Maid = shared('Maid')
--= Class Root =--
local NotificationPane = setmetatable({ }, BasicPane)
NotificationPane.ClassName = 'NotificationPane'
NotificationPane.__index = NotificationPane
--= Object References =--
local TimerMaid = Maid.new()
--= Constants =--
--= Variables =--
--= Internal Functions =--
--= API Functions =--
function NotificationPane:UpdateNotification(Description : string, Time : number, TotalTime : number) : nil
self._title.Text = Description
self._timer.Text = UtilFunctions:FormatTime(Time)
AnimNation.target(self._banner, {s = 10, d = 0.5}, {Size = UDim2.fromScale(Time / TotalTime, 0.05)})
end
function NotificationPane:StartTimer(Time : number, Description : string) : nil
local startTime = os.clock()
local lastChanged = os.clock()
if TimerMaid then
TimerMaid:Destroy()
end
TimerMaid = Maid.new()
self._timer.TextStrokeColor3 = Color3.fromRGB(0, 0, 0)
self:UpdateNotification(Description, Time - (os.clock() - startTime), Time)
TimerMaid:GiveTask(RunService.Heartbeat:Connect(function()
local timeLeft = Time - (os.clock() - startTime)
local timeSinceLastChange = os.clock() - lastChanged
if timeSinceLastChange >= 1 then
if timeLeft <= 1 then
self:Hide()
elseif timeLeft <= 10 then
self:UpdateNotification(Description, timeLeft, Time)
AnimNation.impulse(self._timer, {s = 10, d = 0.5}, {Size = UDim2.fromScale(1, 1)})
self._timer.TextStrokeColor3 = Color3.new(255, 0, 0)
else
self:UpdateNotification(Description, timeLeft, Time)
self._timer.TextStrokeColor3 = Color3.fromRGB(0, 0, 0)
end
lastChanged = os.clock()
else
self:UpdateNotification(Description, timeLeft, Time)
end
end))
end
function NotificationPane:Show() : nil
AnimNation.target(self._holder, {s = 10, d = 0.5}, {Position = UDim2.fromScale(0, 0)})
end
function NotificationPane:Hide() : nil
AnimNation.target(self._holder, {s = 10, d = 0.5}, {Position = UDim2.fromScale(0, 1)})
end
--= Initializers =--
function NotificationPane.new()
local self = setmetatable(BasicPane.new(GuiTemplates:Clone("NotificationPaneTemplate")), NotificationPane)
self._holder = self.Gui.Holder
self._banner = self.Gui.Holder.Banner
self._title = self.Gui.Holder.Title
self._timer = self.Gui.Holder.Timer
self._visible = true
self:SetVisible(false, true)
return self
end
--= Return Module =--
return NotificationPane
UI Design Examples
A lot of these take inspiration from Material Design and things I have seen elsewhere.
Design Examples
My designs are all over the place, enjoy looking at them though, I do them for fun mostly.
PAYMENT
Scripting // UI Design | Building | Graphics Design |
---|---|---|
I work for either percent 20% + or one off payments that exceed R$ 100,000. This is due to lack of availability to join new projects. | I am currently not accepting commissions on building, but I may consider joining a project if it is intriguing enough for me. | I usually do graphics for either free or really cheap, since I do not do commissions for this often. |
CONTACT ME
Discord or Devforum messages exclusively.
TDK#0001
Thank you for viewing my portfolio!