Elysium: The Forsaken Dungeons

A steampunk action RPG for Roblox, set after the world collapsed. I build how it moves, how its abilities look, and the places players explore.

An overgrown industrial courtyard: rusted yellow pillars and pipes wrapped in vines, a glowing blue teleport pad in front, and small white helper robots standing nearby.
Old tech, taken back by the forest: an overgrown courtyard with a glowing pad and helper robots.

Movement system

A client-side controller that replaces Roblox's instant start, stop and turn with momentum and weight, then drives motion-capture animation from the character's real speed.

Click the floor, then move with WASD or the arrow keys. Hold Shift to sprint, X to walk, C to crouch. On touch, hold a finger where you want to go. The blue line is the predicted path, the same one the game draws in Studio.

Weighted steering

The character turns toward the stick at up to 240° a second and builds to speed over about 0.85 seconds. Sharp turns cost speed, and braking is capped so a sprint takes a couple of planted steps to stop instead of snapping to zero.

Animation that matches the feet

Idle, walk, jog and sprint loops are blended by measured ground speed. Every moving clip shares one gait phase, offset so the left heel lands at the same moment in each, so changing pace never pops the feet. Stop clips enter at the frame that best matches the current stride.

Mocap drives the body

Start and stop clips carry their recorded speed curves, and the controller follows them, so the body accelerates exactly as the capture did. Raw hip speed wobbles with each step, so the curves are smoothed to rise or fall in one motion.

Jumps, landings and lean

Jumps have a short takeoff before leaving the ground and limited air control. Hard landings slow the character briefly, and a sprint jump recovers to full speed over 1.5 seconds. The torso banks into turns and rocks back onto the heels when braking, up to 7°.

Every input, every edge case

Keyboard, gamepad and touch all work, keeping analog stick strength. Sprint and crouch toggle on stick clicks. Menus, text boxes and lost window focus cancel held modes, and slows from other systems are respected as a speed cap.

Turning eases toward the input but never faster than the turn-rate cap.
local function rotateToward(from, target, dt, maxRate)
  local angle = math.atan2(from:Cross(target).Y,
    math.clamp(from:Dot(target), -1, 1))
  local change = math.clamp(
    angle * (1 - math.exp(-dt / number("TurnResponse", 0.16, 0.03, 0.6))),
    -maxRate * dt, maxRate * dt)
  return CFrame.fromAxisAngle(Vector3.yAxis, change)
    :VectorToWorldSpace(from), change
end
Braking caps deceleration so the stop animation can carry the last step.
local braking = not stopSpeed and desired < speed - 0.5
  and not crouchLimit
local eased = speed + (desired - speed) * (1 - math.exp(-dt / response))
if braking then
  speed = math.max(eased,
    speed - number("BrakeDeceleration", 30, 5, 200) * dt)
else
  speed = eased
end
Each loop is nudged back onto the shared gait phase so the feet stay in sync.
local base = l.len * phaseVel
local want = wrap(self.phase + l.offset) * l.len
local err = want - l.track.TimePosition
if err > l.len/2 then err -= l.len
elseif err < -l.len/2 then err += l.len end
if math.abs(err) > l.len * .08 then
  l.track.TimePosition = want          -- far off: snap
  l.track:AdjustSpeed(base)
else
  l.track:AdjustSpeed(math.max(0, base + err * 6)) -- close: steer
end
ModeKeySpeed (studs/s)
SprintShift or L318.0
JogDefault11.9
WalkX4.4
CrouchC or R33.4
In game: walk to jog to run with no foot pops, and the Studio trajectory line under the character.

Water ability VFX

Stylized water effects for player abilities, built and tuned in a dedicated test place before they go into the game.

World-building

Humanity's technology turned against it, and nature has taken the ruins back. The look is 1850s Britain with obsolete, half-reclaimed tech.

Item prompts

Custom pickup prompts that replace Roblox's default prompt with a card showing the item, its class, quantity and rarity. This UI is a work in progress, so the design will change.

E Pick up

The items here are examples. In game, each prompt reads them from values stored on the prompt.

  • One prompt, any item

    The card is cloned for each prompt in range and filled from values on the prompt: item name, class, quantity, description and rarity. Designers tag an item once and the UI follows.

  • Rarity you can read at a glance

    Five rarities each set the card's color. Legendary items switch to a display font with a gold gradient. Cursed items get a violet gradient and scramble their text before revealing a message.

  • Feedback on pickup

    Triggering the prompt collapses the card and fades the text out, then it eases back when released. Connections are cleaned up when the prompt leaves view.

Default-style prompts are left alone; custom ones get the Elysium card.
ProximityPromptService.PromptShown:Connect(function(prompt, inputType)
  if prompt.Style == Enum.ProximityPromptStyle.Default then
    return
  end
  prompt.MaxActivationDistance = 40
  local gui = getScreenGui()
  local cleanupFunction = createPrompt(prompt, inputType, gui)
  prompt.PromptHidden:Wait()
  cleanupFunction()
end)