My RolesTechnical Designer → Lead Programmer & Lead Technical Designer
StatusOn Steam, in development
Showcased AtLevel Up Toronto · Sheridan Games Fest
Steam Wishlists320+
A computer is infected and you're the antivirus. Up to four players fight waves of malware, vacuum up the data
they drop, and deposit it into MOM to restore the system. The brief was an 8-month build of a real, marketable
game start to finish, not a vertical slice. Built by a 6-person team, now on Steam and still in development.
I joined as a technical designer, which on this team meant designing systems and then building them myself in
Blueprints rather than handing a spec to someone else. In January our lead programmer stepped down and I took
that role on top of the design work. I've held both since: lead programmer and lead technical designer. The two
studies below are the systems I owned end to end, one that failed for seven months before I cut it, and one
that had to work perfectly on a specific day.
What I Owned
Shop & Economy System
Designed and programmed the whole spend-your-data economy, three versions of it
Built the buy-feed instrumentation that finally made the failure diagnosable
Ran 3 formal playtest sessions, then recommended cutting my own system
Helped design the random per-round ability system that shipped in its place
Enemies & Wave Structure
Helped design the enemy types and how waves escalate round to round
Built on the theme that every enemy is a real internet virus
Part of the original group that expanded the vacuum into the core mechanic
Multiplayer Groundwork
Designed and programmed the LAN path our two public showcases ran on
Steam integration groundwork for online play
Helped start the early session loop; our lead programmer at the time built out much of it
Lead programmer on the project since January 2026
Shipping It
Builds, publishing, and every push to Steam
Online media and marketing around the store page
Programming direction and coordination across the team
Case Study: The Team Economy
The system I owned end to end, design and code. It took seven months, went through three
versions and two replacements, and the thing I'm proudest of is the decision to delete it. This is the whole
arc, including the parts that didn't work.
01 The problem I was
solving
The core loop was already set: kill malware, vacuum the corrupted data it drops,
deposit that data into MOM to push a restoration bar toward 100%. Hit 100% and the squad wins. What the
loop didn't have was a power curve. Round 12 played identically to round 2 except there were more enemies,
so the game got harder while the players stayed the same. Every co-op shooter I looked at solves this with
some version of "spend what you collect to get stronger."
So what I set out to do was fairly specific. Give players a way to get
stronger over a run, using the data they were already collecting, without wrecking the shared win
condition. That last bit is where the next seven months went.
The constraint that made it hardThe resource you spend and the
resource you win with are the same resource. Spending always has to cost the team progress. No commercial
co-op shooter I could find had shipped that exact shape, which I read at the time as an opportunity.
Worth seeing the scope this lived inside. Shop is one column of
twelve on our production board, and it was never anyone's full-time job. A six-person student team
spending seven months on one column is the cost I'm accounting for at the end of this study.
02 Version 1: the shared
bank
My original concept sketch. The bet is in the fourth tab: SQUAD, a tier of team-wide
purchases anyone could buy for everybody. Data siphoned into MOM went into one global bar, and anyone
could spend from that same bar. I chose shared over individual deliberately. A shared pool means every
deposit matters to everyone, which is the co-op feeling I wanted, and it means a player having a bad
round still benefits from the team's work.
The prediction I wrote down was that players would negotiate purchases out loud in voice chat. That
negotiation was supposed to be the fun part.
The version I built and put in front of testers. Note the
restoration percentage sitting directly above the prices. I put it there so the cost would read as a
trade-off. It turned out to be the exact thing that made spending feel like self-harm.
The artist's pass over the same information architecture. Useful
data point in hindsight: this changed nothing about how the system tested. When a design fails on the
economy, art cannot save it, and I stopped treating polish as a variable after this.
What brokeThe shared pool became a shared piggy bank that anyone
could drain. One player could contribute nothing all round, walk up to the shop, and spam-buy until the
bar hit zero. They got strong. Everyone else lost ten minutes of work and got nothing. The negotiation I
predicted never happened, because there was no mechanism to negotiate with.
03 Making the failure
visible
For a while the feedback we got back was too vague to act on. People kept saying the
shop "felt bad" and couldn't tell us why, and I had no way to argue with that. What eventually helped
wasn't a design change at all. I put a leaderboard on screen, the Fortnite kind, showing every player's
name next to whatever they'd just bought, and pushed purchases into the same feed as the kills.
This turned an invisible economy into a public one, and the diagnosis arrived within a single
session. A tester bought sixteen upgrades in one round. The whole table watched the bar fall in real
time, and the voice recording has someone saying "no Marwan, why did you spend all the money" while a
team sitting at 90% restoration slid back toward round 60.
The same feed surfaced a second problem I hadn't been looking for: a meaningful share of testers never
opened the shop at all. Some didn't know it existed. That's a tutorialization failure sitting
underneath the design failure, and without the feed I would have kept reading it as
disinterest.
Building the buy feed. This is the change that made the rest of the
study possible. Everything I learned after this point came from being able to see who spent what, when,
in front of whom.
What the surveys actually said
We ran three formal playtest sessions, roughly ten games each, with a Google Form afterward. The team
read 20 to 30 written responses per session. Two complaints repeated across all three, nearly word for
word: why does buying an upgrade take away from my own restoration progress, and why can
one player erase my work without me getting anything out of it. Roughly half of respondents said
they never used the shop. The other half described spending as an actively negative act.
Several people compared it unfavourably to R.E.P.O., which also uses a shared wallet. I went and
studied why R.E.P.O. gets away with it: a teammate can physically lift an item back out of the cart
before checkout. The shared pool works there because there's a veto, the veto is diegetic, and it takes
one second. Anti-Virus Squad is a fast third-person shooter with no cart and no downtime, and I never
found a way to add a veto that didn't require pausing the match to ask permission. That's the honest
end of the investigation. I identified the missing ingredient and could not find a version of it that
fit our game.
04 Versions 2 and 3: fixing it
in place
Version 2, spend from your own backpack. Keep the shared goal, move the wallet. You
could now spend data you were currently carrying, before depositing it. This solved the problem I had
actually diagnosed: buying became an individual choice and could no longer touch anyone else's progress.
We tested a full round. It traded the fairness problem for a luck problem. A player who happened to find
less data simply couldn't buy anything while their teammates got stronger, and feedback was still
negative.
Version 3, a soft cap. If the pain is watching the bar hit zero, floor the bar at 10%
so there's always progress left. This is the version I'd defend the least in hindsight, because it
treats the symptom. It failed in internal testing and again in public testing. Watching a teammate spend
from 99% down to 10% for a laugh feels exactly as bad as watching it hit zero. The number was never the
problem. The attribution was.
The pattern I missed at the timeThree versions, three different
mechanisms, one unchanged premise: that spending team progress could be made to feel good. I was iterating
inside an assumption instead of testing the assumption.
05 Attacking the other
side: earning
Before giving up on it I tried coming at it from the other end. If spending hurt
because data was scarce, maybe I could just make data less scarce. So I tried more enemies per wave, then
bigger drops per kill. Both of them fell over the same way and it's worth writing down, because it's a
tuning trap rather than a design one and I didn't see it coming.
Enemies too easy or data per kill too high, and nobody repairs firewalls, they just
farm kills. Enemies too hard, and players die before a repair finishes. Either way one of the two
activities eats the other.
The fix came from Call of Duty zombies' boarded windows:
repairing a firewall pays data back instead of only costing time. It's the first thing in this
study that made spending feel survivable, because it gave the economy a second faucet.
I tuned the payout deliberately small, so it only adds up if all
four players split to different firewalls at once. That turned a balance number into a coordination
mechanic, and it's the one piece of the economy work that survived the cut and is still in the shipped
game.
06 What it looked like in the
engine
First pass at purchase logic, client-side and held together with
placeholder comments like "No Ram Yet So We Skip This." Fine for answering "is this fun," and
completely unshippable in a four-player game where the client can lie about its own
wallet.
Where it ended: every purchase is a request the server validates
and applies, with both solo and squad tiers still supported. I rebuilt this properly even while the
design was on trial, because a prototype that desyncs generates feedback about desync, not about the
economy.
Most of those seven months looked like this and not like the
trailer. Half the screen is server logs I was reading live to confirm a purchase actually replicated to
every client before I trusted a single word of tester feedback.
07 Cutting it
Level Up Toronto and NEXTgen were both approaching and there was a long list of
systems that still needed to exist. After seven months I stopped trying to fix the shop in place and
recommended we delete the entire spend-your-progress premise. The team agreed. Data no longer comes out of
the player at all.
The part I want on the record is that cutting it didn't immediately work either.
Replacement 1: no upgrade system at all. We stripped power progression out and ran a
flat five-round vertical slice. It failed differently. By round four or five the difficulty curve outran
a static player, and multiple complete playthroughs ended with nobody winning a single run. A spectator
who never sees anyone win has no reason to want a turn.
Replacement 2: drop upgrades on the floor. Rejected on paper before we built it. It's
the same hoarding problem relocated. One fast player vacuums every drop and the other three get nothing,
which is exactly the failure I'd spent seven months documenting.
What shipped. Every round, each player is automatically handed one random ability
from a pool: more data capacity, faster vacuuming, faster healing, faster firewall repair, more
damage. Rolls are per-player and not synced, so four teammates can be running four different builds in
the same match.
It works because of what it removes. Nobody chooses it, so nobody can hoard it. Nobody pays for it,
so nobody loses progress. Nobody watches a teammate spend, so there's nothing to resent. The "I got
stronger this round" beat I wanted from the shop survives, and every failure mode I'd catalogued is
structurally impossible rather than balanced against.
What I'd do differently
Early on I was proud that I couldn't find another game doing a shared piggy-bank economy this way. It
read like open territory. Around month six the real explanation landed: nobody had shipped it because
it's an unsolved design problem, not because nobody had thought of it. Absence of prior art is
ambiguous evidence, and I read it as encouragement.
I'd time-box a challenge like this to about three months now. Not because the idea was bad, it was
genuinely interesting, but because we got attached early and that attachment spent development time
other systems needed. A studio with a dozen designers and a budget can afford to sit with an open
problem. We were an unpaid student team at 20 to 40 hours a week each, juggling four or five systems,
with maybe an hour a day to meet on any one of them. The mistake wasn't the idea. It was not setting a
date by which the idea had to prove itself.
The second thing I'd change is order of operations. I spent versions 1 through 3 iterating on
mechanism while the premise went untested. If I'd written the premise down at the start as a claim that
could be proven wrong, "players will accept spending shared progress as long as the spend is fair," I
could have killed it in month two instead of month seven.
A note on credit, because it matters more than the
claim does. The core concept came out of a full team sit-down, not from me. What I owned was the economy
system itself: the design, the Blueprints, the playtest instrumentation, the iteration, and the
recommendation to cut it. Anything structural went back to the group before it got committed. We put a
combined few hundred hours into voice calls building this game together.
Case Study: Shipping to a Room Full of Strangers
A different kind of problem, with a hard deadline instead of an open question. Two public
showcases were booked. A four-player online co-op game had to run all day on a folding table, and convention
wifi is not something you bet a demo on.
01 The constraint
Our normal flow was Steam sessions over the internet: main menu, host or find a
server, lobby, launch. That's fine in a bedroom and hostile at a convention. Venue wifi is congested and
sometimes sitting behind a captive portal, Steam matchmaking needs to reach the internet, and the failure
mode in front of a stranger isn't a bad match, it's a black screen while four people stand there holding
controllers.
There's also a throughput problem nobody warns you about. A booth visitor gives you
maybe ninety seconds of patience. If joining takes longer than the walk from the queue to the chair, they
leave.
02 What I built
I designed and programmed a LAN path that bypasses Steam entirely, so four machines
on a switch could find each other and start a match with no internet at all. I also did the Steam
integration groundwork on the online path, and helped start the early session loop, main menu through
lobby into the map, which our lead programmer at the time then built out a large part of.
ResultBoth booths ran all day without a restart. Four strangers
could sit down and be in a match in seconds, repeatedly, for hours.
The first thing a booth visitor sees. Everything upstream of this
frame, the lobby, the session handshake, the LAN discovery, is invisible when it works and is the
entire demo when it doesn't.
The showcase map from above. Enemy lanes converge on the base
from four directions, which is what forces the firewall split from the economy study into something a
stranger understands without a tutorial.
03 What it was for
Four laptops, one switch, no internet. This photo is the
deliverable the LAN work was written for.
Deadclub Studios at Level Up Toronto. Six people, eight months, a
game strangers queued to play.
NEXTgen at the Toronto Tool Library, shot by the event's
photographer. Watch the players rather than the screen. Every one of those sessions started because the
LAN path found the host without asking anyone's permission.
Two More Systems, Briefly
Shorter than the studies above because my ownership was shared. Both are team-originated
ideas I helped shape and implement.
Enemies & Waves
The design rule we worked to: every enemy has to break a different solo habit, or
it's a reskin.
Wave 1 · Baseline
ILOVEYOU (the swarmer)
Grows in numbers every wave. Can be vacuumed like anything else, which teaches the push and pull loop
on a target that doesn't punish you for practising on it.
Wave 5 · First spike
Virus Cloud
Leaves a damaging trail and holds more data than one vacuum can drain. Breaks soloing by arithmetic
rather than by difficulty: two players, or one player making two trips while it keeps hurting the
team.
Wave 3+ · Reaction test
Popup Bug
Picks a random player and flies through walls at them. Zero health, so damage is irrelevant. The only
counter is vacuuming it in time, which forces someone to drop what they're doing.
The Popup Bug landed. Stack these three in one wave and no single
player can cover everything, which is the actual mechanic. The Y2K virus theming is the wrapper, not the
design.The Vacuum
Started as a team idea for picking up loot, and it's the thing our post-mortem
says we should have built the rest of the game around and didn't.
Why the timing rules exist
Two-second grace period before a player gets pulled in, with a wind vignette. You can
still move and shoot while it happens, which is what makes it a threat you can answer instead of a stun
you sit through.
Nozzle clog. The first thing that reaches you sticks to the gun and blocks shooting
or picking anything else up. This is the cost that stops the vacuum from being strictly better than the
gun.
Hold two seconds, then release to launch with a speed boost. Release early and it
drops. One object at a time, so the skill expression is in choosing what to hold.
Vacuuming a teammate is legal and we left it that way on purpose.
Depending on when you do it it's a rescue or a prank, and letting it be both was cheaper than trying to
tell them apart in code.
What our post-mortem said about this, which I'd rather not leave out
When the team wrote up the capstone at the end, one of the takeaway slides was about the vacuum, and
it wasn't a compliment. The wording was that looking back we should have made sure vacuuming felt
important, and that as the unique mechanic of our game everything else should have incorporated it and
taken advantage of it.
I agree with that. We built a genuinely unusual mechanic and then spent most of the eight months on
systems sitting next to it rather than on top of it. The shop, the firewalls and the wave structure
would all still basically work if you swapped the vacuum out for a pickup button, and that's the
honest test of whether a gimmick is actually load bearing. It isn't a bug we shipped, it's a
prioritisation thing, and it's the one I think about most.
Getting It Out the Door
I handled builds, publishing and every push to Steam, plus the store page and the marketing around it.
179 wishlists before the capstone term ended, 320+ now. The unglamorous part is the
point: a real release pipeline meant playtesters got keys the way players get keys, and showcases ran on
versioned stable builds instead of whatever was on someone's laptop that morning.
Build testing on one monitor, trailer edit on the other. On a
six-person team marketing isn't a separate department, it's the same afternoon.
The trailer's closing frame. Every decision in the two studies
above only counts if someone outside the classroom ever presses this.
What I Learned
Kill Your Own Designs
My economy concept didn't survive contact with players. I'd designed it, programmed it, and still had
to be the one to say it wasn't working. Redesigning it instead of defending it made the game better
and made me a better designer - the data doesn't care how attached you are to an idea.
Groundwork Buys Freedom
Because networking and Steam plumbing existed early, the whole team could test ideas with real online
playtesters instead of guessing in a vacuum. The shop redesign only happened as fast as it did because
we already had a pipeline to put builds in front of strangers.
Shipping Is a Skill
Builds, store pages, keys, marketing. None of it is glamorous and all of it is why people outside our
classroom have actually played the game - 320+ wishlists don't happen from a good idea sitting on a
hard drive.