AVAILABLE FOR COMMISSIONS

Roblox systems scripter.
Luau, Discord bots,
economies that scale.

I'm Hitchy — founder of HTC Games and a backend-focused Roblox scripter. I build the data layer, economy math, and security systems that idle games, sims, and Discord communities run on.

4+
Games shipped/live
6
UI designs
Open
Taking commissions
Aug 25
Next launch
EconomyService.lua
-- alien ore payout, prestige + rune scaled local function calculatePayout(player, alien) local base = alien.baseRate local prestige = PrestigeService.getMultiplier(player) local rune = RuneService.getBonus(player, alien) return BigNumber.multiply(base, prestige * rune * 1.0) end
Toolkit

What I build with

Roblox Studio for the game layer, Python for the community layer. Everything ships production-ready, not prototype-grade.

Luau / Roblox Studio

DataStores & ProfileStore, module-based architecture, remote security, tool physics, NPC/animation rigging, incremental & sim economies.

Discord.py 2.x

Multi-cog bot architecture, moderation & leveling systems, ticket/dropdown flows, translation pipelines, self-hosted deployment.

Systems design

BigNumber math for idle scaling, prestige/rebirth loops, rarity & drop-rate tables, UI architecture within Lua's local-register limits.

Selected work

Projects

A mix of shipped HTC Games titles, work in progress, and client commissions.

01

Alien Incremental In development

Idle/incremental Roblox game — 8 passive-mining aliens, a 7-tier prestige system with infinite ascension, rebirth sub-loop, and a 9-rarity rune system. Bioluminescent alien-tech visual direction.

DataManagerBigNumberEconomyServiceProfileStore
Lead scripter
Sept 9 launch target
02

City Clicker Live

HTC Games incremental — Max buy (x1/x10/Max), decillion-scale number formatting, promo codes, and click-feel juice (bounce, lucky-click flash, floating popups). Full charcoal/amber UI restyle.

UI systemsNumber formattingGame feel
Lead scripter
Update 5 shipped
03

ARK Community Bot Delivered

Full production Discord.py bot for an ASA/ASE server — moderation, leveling/XP, security, a ticket system with map dropdowns, and a standalone translation sub-bot.

discord.py 2.xMulti-cogClient commission
Solo build
Client delivery
04

Hatch a Weirdo Paused

Brainrot egg-hatching simulator — 11 rarities, 55 named creatures, mutations, wave systems, and rebirth mechanics. Fixed critical economy and sell-system bugs across a large legacy codebase.

Sim economyBug remediationNPC rigging
Lead scripter
HTC Games
Portfolio

UI Designs

UI concepts and mockups — menu systems, panels, and in-game interface work.

Pet inventory panel with search bar, Equip Best / Delete Mode / Filter buttons, and a grid of pet cards in gold and purple rarity colors

Pet inventory panel

Search, quick-action buttons, and a rarity-colored pet card grid with a bright cartoon UI style.

Matchmaking panel with a Casual header, mode cards for 3v3, 1v1, 2v2, Training, and FFA, plus a username banner

Matchmaking panel

Mode-select cards with diagonal-shine gradients and hex pattern overlay, plus a Competitive toggle and player banner.

Icon set with rounded square buttons for Shop, Inventory, Pets, Settings, and Trading, each with a cartoon icon and colored gradient background

Navigation icon set

Shop, Inventory, Pets, Settings, and Trading buttons — cartoon icons on rounded halftone-textured gradient tiles.

Runes panel with a glowing cyan neon-outlined header and a row of rune cards showing rarity, level, and stat boosters

Runes panel

Neon cyan-outlined dark UI with a scrollable row of rune cards — rarity tag, level, progress bar, and stat booster list.

Quests panel with glowing neon header and stacked quest cards showing title, reward, and progress bar

Quests panel (neon)

Stacked quest cards with reward counter and progress bar, matching neon cyan glow style with a W/D toggle button.

Game mode select grid with 1v1, 2v2, 3v3, 4v4, 5v5 cards and a larger Ranked/Unranked toggle card with player count

Game mode select

Mode grid (1v1 through 5v5) with a larger Ranked/Unranked card and live queue count, diagonal texture matching the matchmaking panel.

Shop panel with a 2X Luck boost offer and a Starter Bundle offer, cartoon icons on a halftone-textured background

Shop panel

Timed boost and starter bundle offers with cartoon icons, item preview slots, and gem-cost pricing on a halftone-textured card style.

Portfolio

Code Samples

Representative scripts showing how I structure server-authoritative systems, economy math, and bot logic. Full projects available on request.

Server-authoritative hit validation

Luau

Distance, angle, rate-limit, and position-mismatch checks for a melee combat system — the kind of pattern used in the Last Dance combat rewrite.

-- CombatValidator.lua
-- Server-authoritative hit validation for a melee/ranged combat system.
-- Rejects client-reported hits that fail distance, angle, or rate checks.

local RunService = game:GetService("RunService")

local CombatValidator = {}
CombatValidator.__index = CombatValidator

local MAX_HIT_DISTANCE = 12
local MAX_ANGLE_DEGREES = 65
local MIN_HIT_INTERVAL = 0.35 -- seconds, matches weapon swing cooldown

local lastHitTimestamps = {} -- [player.UserId] = os.clock()

function CombatValidator.new(config)
	local self = setmetatable({}, CombatValidator)
	self.hitboxPadding = config.hitboxPadding or 1.5
	return self
end

function CombatValidator:IsRateLimited(attacker)
	local last = lastHitTimestamps[attacker.UserId]
	if last and (os.clock() - last) < MIN_HIT_INTERVAL then
		return true
	end
	lastHitTimestamps[attacker.UserId] = os.clock()
	return false
end

function CombatValidator:ValidateHit(attacker, target, reportedHitPosition)
	local attackerRoot = attacker.Character and attacker.Character:FindFirstChild("HumanoidRootPart")
	local targetRoot = target.Character and target.Character:FindFirstChild("HumanoidRootPart")

	if not attackerRoot or not targetRoot then
		return false, "MissingCharacter"
	end

	if self:IsRateLimited(attacker) then
		return false, "RateLimited"
	end

	local distance = (targetRoot.Position - attackerRoot.Position).Magnitude
	if distance > MAX_HIT_DISTANCE + self.hitboxPadding then
		return false, "OutOfRange"
	end

	local toTarget = (targetRoot.Position - attackerRoot.Position).Unit
	local facing = attackerRoot.CFrame.LookVector
	local angle = math.deg(math.acos(math.clamp(facing:Dot(toTarget), -1, 1)))
	if angle > MAX_ANGLE_DEGREES then
		return false, "BadAngle"
	end

	-- Sanity-check the client-reported hit position against the target's
	-- actual position, catching spoofed RemoteEvent payloads.
	local reportedDelta = (reportedHitPosition - targetRoot.Position).Magnitude
	if reportedDelta > self.hitboxPadding * 2 then
		return false, "PositionMismatch"
	end

	return true
end

return CombatValidator

BigNumber module

Luau

Mantissa/exponent number type for incremental games — keeps precision past 1e300+ and formats for display, same approach used in Alien Incremental's economy.

-- BigNumber.lua
-- Compact arbitrary-scale number type for idle/incremental economies.
-- Stores values as {mantissa, exponent} to stay accurate past 1e300+
-- without floating point precision loss, and formats for display.

local BigNumber = {}
BigNumber.__index = BigNumber

local SUFFIXES = { "K", "M", "B", "T", "Qa", "Qi", "Sx", "Sp", "Oc", "No" }

local function normalize(mantissa, exponent)
	while mantissa >= 10 do
		mantissa /= 10
		exponent += 1
	end
	while mantissa < 1 and mantissa > 0 do
		mantissa *= 10
		exponent -= 1
	end
	return mantissa, exponent
end

function BigNumber.new(value)
	local mantissa, exponent = normalize(value, 0)
	return setmetatable({ mantissa = mantissa, exponent = exponent }, BigNumber)
end

function BigNumber.__add(a, b)
	local diff = a.exponent - b.exponent
	if math.abs(diff) > 15 then
		return diff > 0 and a or b -- smaller value is negligible at this scale
	end
	local mantissa = a.mantissa + b.mantissa * (10 ^ -diff)
	local m, e = normalize(mantissa, a.exponent)
	return setmetatable({ mantissa = m, exponent = e }, BigNumber)
end

function BigNumber.__lt(a, b)
	if a.exponent ~= b.exponent then
		return a.exponent < b.exponent
	end
	return a.mantissa < b.mantissa
end

function BigNumber:ToString(decimals)
	decimals = decimals or 2
	if self.exponent < 3 then
		return string.format("%." .. decimals .. "f", self.mantissa * 10 ^ self.exponent)
	end

	local suffixIndex = math.floor((self.exponent - 3) / 3) + 1
	local suffix = SUFFIXES[suffixIndex] or ("e" .. self.exponent)
	local shortMantissa = self.mantissa * 10 ^ ((self.exponent - 3) % 3)
	return string.format("%." .. decimals .. "f%s", shortMantissa, suffix)
end

return BigNumber

Ticket claim system

Python / discord.py

Prevents double-claiming support tickets, with an auto-release on timeout — part of the ARK community moderation bot's ticket cog.

# ticket_claims.py
# Admin claim system for the ARK ticket bot — prevents two staff members
# from double-claiming the same ticket, with an auto-release on timeout.

import discord
from discord.ext import commands, tasks
from datetime import datetime, timedelta

CLAIM_TIMEOUT_MINUTES = 30

class TicketClaims(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.active_claims: dict[int, dict] = {}  # channel_id -> {staff_id, claimed_at}
        self.release_stale_claims.start()

    def cog_unload(self):
        self.release_stale_claims.cancel()

    @commands.hybrid_command(name="claim", description="Claim this support ticket")
    async def claim(self, ctx: commands.Context):
        channel_id = ctx.channel.id
        existing = self.active_claims.get(channel_id)

        if existing and existing["staff_id"] != ctx.author.id:
            claimer = ctx.guild.get_member(existing["staff_id"])
            await ctx.send(
                f"This ticket is already claimed by {claimer.mention if claimer else 'another staff member'}.",
                ephemeral=True,
            )
            return

        self.active_claims[channel_id] = {
            "staff_id": ctx.author.id,
            "claimed_at": datetime.utcnow(),
        }
        await ctx.channel.edit(name=f"claimed-{ctx.channel.name.split('-', 1)[-1]}")
        await ctx.send(f"🎫 Claimed by {ctx.author.mention}.")

    @commands.hybrid_command(name="unclaim", description="Release your claim on this ticket")
    async def unclaim(self, ctx: commands.Context):
        existing = self.active_claims.get(ctx.channel.id)
        if not existing or existing["staff_id"] != ctx.author.id:
            await ctx.send("You haven't claimed this ticket.", ephemeral=True)
            return

        del self.active_claims[ctx.channel.id]
        await ctx.send(f"Ticket released by {ctx.author.mention}.")

    @tasks.loop(minutes=5)
    async def release_stale_claims(self):
        cutoff = datetime.utcnow() - timedelta(minutes=CLAIM_TIMEOUT_MINUTES)
        stale = [cid for cid, data in self.active_claims.items() if data["claimed_at"] < cutoff]
        for channel_id in stale:
            del self.active_claims[channel_id]

async def setup(bot):
    await bot.add_cog(TicketClaims(bot))

Exploit guard / remote validation

Luau

Whitelists remote payload shapes, rate-limits requests per player, and flags speed/teleport anomalies — the anti-exploit layer that sits in front of gameplay logic.

-- ExploitGuard.lua
-- Server-side remote validation layer — sanity-checks every RemoteEvent
-- payload before it reaches gameplay logic, rejecting malformed or
-- speed-hacked client input.

local ExploitGuard = {}
ExploitGuard.__index = ExploitGuard

local MAX_WALKSPEED = 32
local TELEPORT_DISTANCE_THRESHOLD = 60 -- studs per heartbeat, flags fly/noclip
local requestLog = {} -- [player.UserId] = { count, windowStart }

function ExploitGuard.new(remoteWhitelist)
	local self = setmetatable({}, ExploitGuard)
	self.remoteWhitelist = remoteWhitelist -- table of { [remoteName] = expectedArgTypes }
	self.lastPosition = {}
	return self
end

function ExploitGuard:ValidatePayload(remoteName, player, ...)
	local expected = self.remoteWhitelist[remoteName]
	if not expected then
		return false, "UnknownRemote"
	end

	local args = { ... }
	if #args ~= #expected then
		return false, "ArgCountMismatch"
	end

	for i, expectedType in ipairs(expected) do
		if typeof(args[i]) ~= expectedType then
			return false, "ArgTypeMismatch:" .. i
		end
	end

	return self:CheckRateLimit(player, remoteName)
end

function ExploitGuard:CheckRateLimit(player, remoteName, limit, windowSeconds)
	limit = limit or 20
	windowSeconds = windowSeconds or 1

	local key = player.UserId .. ":" .. remoteName
	local entry = requestLog[key]
	local now = os.clock()

	if not entry or (now - entry.windowStart) > windowSeconds then
		requestLog[key] = { count = 1, windowStart = now }
		return true
	end

	entry.count += 1
	if entry.count > limit then
		return false, "RateLimitExceeded"
	end
	return true
end

function ExploitGuard:CheckMovementIntegrity(player)
	local character = player.Character
	local humanoid = character and character:FindFirstChildOfClass("Humanoid")
	local root = character and character:FindFirstChild("HumanoidRootPart")
	if not humanoid or not root then
		return true -- character not loaded, nothing to validate yet
	end

	if humanoid.WalkSpeed > MAX_WALKSPEED then
		return false, "SpeedModified"
	end

	local last = self.lastPosition[player.UserId]
	self.lastPosition[player.UserId] = root.Position
	if last and (root.Position - last).Magnitude > TELEPORT_DISTANCE_THRESHOLD then
		return false, "SuspiciousTeleport"
	end

	return true
end

return ExploitGuard

Menu controller

Luau

Reusable tweened open/close controller for UI panels — debounced input and animation-state tracking so a menu can never get stuck half-open.

-- MenuController.lua
-- Reusable UI controller — tweened open/close, debounced input, and
-- automatic cleanup so panels never get stuck mid-animation.

local TweenService = game:GetService("TweenService")

local MenuController = {}
MenuController.__index = MenuController

local OPEN_TWEEN_INFO = TweenInfo.new(0.28, Enum.EasingStyle.Quint, Enum.EasingDirection.Out)
local CLOSE_TWEEN_INFO = TweenInfo.new(0.18, Enum.EasingStyle.Quint, Enum.EasingDirection.In)
local DEBOUNCE_SECONDS = 0.3

function MenuController.new(frame)
	local self = setmetatable({}, MenuController)
	self.frame = frame
	self.isOpen = false
	self.isAnimating = false
	self.lastToggle = 0

	self.frame.Visible = false
	self.frame.Position = self.frame.Position + UDim2.new(0, 0, 0.05, 0)
	self.frame.BackgroundTransparency = 1

	return self
end

function MenuController:Open()
	if self.isOpen or self.isAnimating then
		return
	end
	self.isAnimating = true
	self.isOpen = true
	self.frame.Visible = true

	local targetPosition = self.frame.Position - UDim2.new(0, 0, 0.05, 0)
	local tween = TweenService:Create(self.frame, OPEN_TWEEN_INFO, {
		Position = targetPosition,
		BackgroundTransparency = 0,
	})

	tween.Completed:Once(function()
		self.isAnimating = false
	end)
	tween:Play()
end

function MenuController:Close()
	if not self.isOpen or self.isAnimating then
		return
	end
	self.isAnimating = true
	self.isOpen = false

	local tween = TweenService:Create(self.frame, CLOSE_TWEEN_INFO, {
		Position = self.frame.Position + UDim2.new(0, 0, 0.05, 0),
		BackgroundTransparency = 1,
	})

	tween.Completed:Once(function()
		self.frame.Visible = false
		self.isAnimating = false
	end)
	tween:Play()
end

function MenuController:Toggle()
	local now = os.clock()
	if (now - self.lastToggle) < DEBOUNCE_SECONDS then
		return -- ignore rapid double-clicks / spam taps
	end
	self.lastToggle = now

	if self.isOpen then
		self:Close()
	else
		self:Open()
	end
end

return MenuController

Snippets are representative examples of systems I've built, written for portfolio display rather than pulled verbatim from client deliverables (which stay private). Happy to walk through real project code on a call.

Proficiency

Where I'm strongest

Backend and systems work first — I can take a UI brief end to end too, but data, economy, and security are where I spend most of my time.

Data & economy systems
Luau / Roblox Studio
Discord bot dev (Python)
Security & anti-exploit
UI scripting
Commissions

Rates

Priced in Robux. Final quote depends on scope — send a brief and I'll confirm a number before starting.

Small
Single system
1k–3k R$
Leaderboards, single UI panels, small standalone scripts.
Medium
Feature build
3k–8k R$
Shop systems, inventories, tool mechanics, Discord bot cogs.
Large
Core systems
8k–20k R$
Full economy/data architecture, prestige loops, multi-cog bots.
Full scope
Full game
20k+ R$
End-to-end backend for a full title, built and maintained.