Emotion Tycoon — working agreement and playbook
Use this whenever the user mentions Emotion Tycoon, its trees, workers, droppers, boosts, events, floors, save slots, game passes, raids, codes, the admin panel, or asks for icons, particles, UI, models, thumbnails or a promo video for it — even if they only describe a symptom ("the tree is stuck", "particles look small", "I'm stuck with $0").
The user is a solo Roblox dev (group "Squashed Stuidos", id 706695552) who hand-draws a lot of the art and is picky about anything that looks "vibecoded" or AI-generated. Everything below comes from their own corrections; treat it as their house style, not a suggestion. They often send long voice-typed batches of requests: turn each batch into a task list, do the quick bugs first, and answer every item in the final report (including the ones you decided against).
The user's standing rules
- Respect their edits. Never overwrite model/UI changes the user made by hand. Read before writing.
- No AI-looking UI. No text tags/chips/badges ("PASS", "NEW", "HOT"), no glossy gradient pills plastered on things, no icons overlapping text fields, no plain floating text lines explaining things. Distinguish things by layout, outline style, colour or grouping instead.
- New windows: clone a window the user already approved (
HUD.FriendModaltwo-column layout,RebirthModal,OfflineModal) and swap its contents, instead of composing one from scratch. A from-scratch window got rejected as "visibly made with AI". Text fields = recessed white box with the dark 3px outline, dark text. - Numbers the player owns look like the cash bar. E.g. Raid Tokens = a clone of
HUD.Cashnext to it with the token icon, hover (PC) / tap (phone) for a tooltip. Always make hover info work on mobile (tap toggles). - Real stud texture for UI backgrounds:
rbxassetid://100839690373358(never a procedural one). - Use their hand-made assets first (IDs below). Don't generate replacements when one of theirs exists.
- End every reply that adds visuals with a short list of assets they could draw to replace placeholders.
- Robux glyph is the private-use char
U+E002. - Don't hallucinate. Search the web / read the code when unsure about an API or ID.
- Don't open a second Roblox Studio. Computer use is only for things MCP can't do (FBX import, Game Bar).
- Never save their .blend (
C:\Users\cosul\Desktop\models_for_roblox\RobloxTycoon.blend); remind them to Ctrl+S. - 3D models in Blender: modifier-based, clean low-poly, flat-shaded; gear in the
/roblox-r6-armorkit style. - No daily rewards (they prefer offline/AFK earnings). Keep "?" mystery hexes everywhere — when a "?" becomes a real node, add new "?" hexes beyond it.
- Decided / rejected (don't re-propose): base protection, skipping rebirth, "Upgrade All" (only a per-NPC Max button), a cosmetics shop, a Trophy tree (Raid Tokens stay; earned by daily top 3 on Rebirths + every 5th rebirth). Weather Machine = exactly 1 per plot. Synergy tutorial: on hold until they ask.
- Never let a player get hard-stuck. Any change to costs/trees/rebirth must keep a path to a working line
(Main has
lineCost+rescuetop-up and a Cash-Tree guard — keep them working).
Studio MCP workflow
- Studio id changes per session — get it with
list_roblox_studios. - Edit datamodel is unavailable in Play mode. The user playtests themselves: check
get_studio_state; while they play you may still READ scripts through the Server datamodel (game.ServerScriptService.Main.Source). Wait for them (poll every few minutes); stop their playtest only if they've been idle for minutes, and say so. If they ask "make sure things saved": edits only persist when made in Edit. execute_luauin Client/Server has its own require cache:require(module)there is a fresh copy, not the running one (monkey-patching it does nothing). Reach running state through the game's remotes (ReplicatedStorage.Remotes.Request:InvokeServer(action, ...), incl.adminops) or instances/attributes. To test Config edits in Edit mode,require(Config:Clone()).- Script edits:
ScriptEditorService:UpdateSourceAsyncviaexecute_luau, exact find/replace withstring.find(src, old, 1, true)and assert the match is unique. Use[==[ ]==]strings (code often contains]]). UImodule's start function is at Luau's 200-local-register limit ("Out of local registers"). Never add new top-level locals there: put new state/functions on the sharedexttable or insidedo ... endblocks.- To test a rare state (e.g. a full line), temporarily change a Config constant in Edit, playtest, then revert it.
- Verify by playtesting with
ET_NoSave:start_stop_play,screen_capture,get_console_output.user_mouse_inputx/y are GUI/screen coords: for a world point useWorldToScreenPoint(= viewport y - 58); for UI useAbsolutePosition. Screenshots are scaled (~0.955 of the 2011px viewport).textInputinto a TextBox doesn't reach it — test redeem-style flows through the remote instead. - DataStores in Studio are the LIVE ones (API access on): anything you write while testing (e.g. test codes) must be deleted afterwards.
Game map (where things live)
ReplicatedStorage.Shared.Config— all tuning: Items, Employees, Perks, Materials, Events, Robux,RobuxClusters, Themes, TreePaths/TreeLayout/RebirthLayout,AURA(who buffs/debuffs which tiles),CAPACITY_PERKS,MAX_LIVE_CUBES(per dropper line) /MAX_PLOT_CUBES, Weather Machine functions (weatherChance,weatherUpgradeCost= share of next rebirth doubling per level,weatherRoll,weatherOwned), Raid defs + tokens.ReplicatedStorage.Shared.Grid— cell maths (20x20 tiles, TILE=4). Rotation r: 0=-Z 1=+X 2=+Z 3=-X.ReplicatedStorage.Shared.VFX— particle presets;VFX.burstmakes one emitter per colour.ServerScriptService.Main— sessions,handlers.*for every remote action (incl.batchfor drag-building,upgradeWeather,redeemCode,buyRaidToken), Weather Machine data (data.wm,Factory.weatherHook), rescue, Heartbeat loop.pushStatecan be held (s.holdPush) during a batch.ServerScriptService.Server.{Factory,Plots,Shop,Events,DataService,Leaderboards,Prices,Raids,Admin,Codes}. Factory: per-line cube counts (session.lineCount,uncount),lineCap,LineFullattribute on droppers, bucketed blocker check (keep it O(n), lines can hold 100 cubes),Factory.holdto batch rebuilds. Admin: admin-onlyops(gift online/offline/cross-server, events, announce, codes). Codes: DataStoreET_Codes_v1(keycodes+uses_<CODE>), kinds cash/scaled/rp/token/boost, dates, max uses (0 = no limit).StarterPlayerScripts.ClientModules.{UI,Build,Cubes,Life,Boards,Aura,Pop}— UI = HUD, trees, modals, inspect panel; Build = ghost, drag/batch placing with see-through placeholders, right-hold delete, move; Aura = the green/red/yellow tile squares. Admin panel UI:ServerStorage.AdminGui(+AdminClient), cloned only into admins' PlayerGui.- Tree canvases are authored nodes in
StarterGui.TreeGui.Window.Pan.{Canvas,RebirthCanvas,RobuxCanvas}.Nodes(attributes Q, R, Ring, Path, Mystery). A new node = rename/convert a "?" node at that cell (removeMystery, setPath) + add the id toConfig.TreePaths/RebirthLayout. Position: cash x = 0.4654 + 0.0691q, y = 0.6062 + 0.0850r + 0.0425q; rebirth x = 0.5 + 0.1230q, y = 0.5 + 0.1300r + 0.0650q. - Studio-only dev remotes:
devEvent,devCash,devRobux,devRobuxRemove,devRobuxReset,devOffline,devTutorial. Admin remotes (admin, op, ...) work in Studio for the owner (gift rp/cash/token to yourself). - Never test on the real save by accident.
workspace:SetAttribute("ET_NoSave", true)in Edit before a throwaway playtest, remove it afterwards.
Known gotchas (each one bit us once)
- Premium NPC place errors left "ghost" tiles →
placebuilds inside pcall with rollback; keep that pattern. - PlayerAdded yields (
Shop.checkPasses, DataStore loads): after each yield check the session is still current, or a player who left gets their plot rebuilt with no owner. PlayerRemoving frees the plot BEFORE saving. - A
UIGradientmultipliesBackgroundColor3— a cloned teal frame with a purple gradient renders navy. Set the background to white when recolouring through the gradient. - Cash bar has a
BumpUIScale: anything positioned from its AbsoluteSize must divide by that scale. - Right mouse button in Build = hold-to-delete; camera pan is middle mouse / WASD.
- Tree drag start must use
UIS.InputBegan(button presses never reachwin.InputBegan). - Floor theme textures go on top of the floor (Texture instance); never change the floor's Material.
- User particle sheets are 2x2 flipbooks with small shapes → scale Size ~2–2.5x; multicolour = multiple emitters.
- Newly uploaded textures can look blurry for a while (Roblox processing).
- High-tier droppers need huge work per stage; weak lines sell for ~$1 (empty cube value).
- Images:
upload_imageworks from a local http server (e.g.http://127.0.0.1:8765/<file>). - FBX pipeline: export from Blender with
use_selection=True, object_types={'MESH'}, apply_unit_scale=True, mesh_smooth_type='FACE'to%LOCALAPPDATA%\Temp\et_export\; import by computer use (Asset Manager → Import → type path → Import), lands inworkspace.<FbxName>. The importer mirrors X: place parts withCFrame.new(-x_b, z_b, y_b)from Blender coords. Preview renders: temporary "ET_Preview" scene → staged images. - In-game outside links aren't allowed: Discord/group go on the game page's Social Links; in-game only a
GroupService:PromptJoinAsync(groupId)"Join group" button.
Monetization layout (current)
- Robux shop = separate islands you pan between (
Config.RobuxClusters: Game Passes, Premium Workers, Cash, Boosts & Events). Adding a pass = add its id to an island'sitems+ add a hex inRobuxCanvas.Nodes. - Passes vs products are distinguished by island and outline animation, never by labels.
- Prices are fetched live (
Server.Prices→ReplicatedStorageattributeRobuxPrices). - Pass IDs: HypeQueen 2026442663, DiamondWorker 2026394625, PassMidas 2025590666, PassLuck 2025848628, PassDrop 2025464639, PassVIP 2026922652, GoldenRobot 2025374681, LayoutSlot3 2026652648, LayoutSlot4 2026010654, Pass2x 2027138654.
- Product IDs: OfflineDouble 3717787338, BuyBlood 3717787331, BuyMeteor 3717787319, BuyThunder 3717787307, BuyGolden 3717787299, BuyRain 3717787292, Boost3x 3717787279, Boost2x 3717787271, CashVault 3717787265, CashBag 3717787258, CashPouch 3717787249, RaidPortal 3717992673, RaidSiphon 3717992684, RaidJunk 3717992698, RaidGloom 3717992711.
- Floors are free rebirth rewards picked in Settings. Factory saves: 2 free slots, slots 3–4 are passes.
- Late-game players have sextillions and 30+ rebirths: price late content as a share of
Config.rebirthCost(scales forever) rather than a fixed number; codes default to "% of next rebirth" for the same reason.
The user's assets
Icons: moneyboost3 105474801162476, moneybag 79223369019300, goldenhour 71253971041485, thunderstorm 106415624997312, moneyvault 114456854945836, moneyboost2 88658276906960, meteor 110778083355096, rain 112383447314124, coinpouch 115820638833486, faster_hoppers 85633043652627, x2coins 100838792374750, crown 89385624200044, midas_touch 108493524899149, bloodmoon_2 79508274280864, moon2 97357609209998, hammer 89643796486723, floppydisk 127943322640811, star 119578070875725, zzz 130218032337173, frost 109343690555707, raid_token 112843349186486, weather_machine 112719886234229, conveyor_full 79879060986006 (line-full sign), backpack_cubes 84466301181838 / crate_cubes 108346564955404 / chest_cubes 131689000211065 (capacity perks).
Floors: ocean_lights 138556700370722, holy 105026190310831, pink 83692624195325, pink_green 136148045549462, redx 124121848293779.
Particles (2x2 sheets): anger 97456853400445, happy_love 83569352224420, bolts 125645422252125, steam 115369146046246, confetti 108450399478144, swirls_sparkles 131593243447656, waterdrops 125415103859140, happy_confetti 103582469151146, money 128140468436252, music_notes 92525208060800, ice_shards 123359736235888.
workspace["Simulator Icon Pack"] (list its Decals for IDs): useful ones — Down arrow 17368169201, Codes
17368032566, MultiGifts 15402969720, Expand 17368183719, Click 17260727409, Rocket 16670799841, Box 17368122337,
Crate 17368402884. CubePets 17368391613 is a DOG — never use it for non-pet things.
Promo video recipe (fully automated, no user clicks after the first approvals)
- Approvals once: computer-use access to Roblox Studio + Game Bar with system key combos, and folder access to
~/Videos(Game Bar saves toVideos\Captures). - Showcase state: set
ET_NoSave, start play, then via the Request remote:devCash, unlock every cash-tree node (loopunlockuntil no progress), clear the layout, build 4 lines (dropper at x=1 r=1, belts x=2..17, seller x=18; workers on both sides facing the belt). Use Dropper2–4 so cubes actually fill and sell for real numbers. - Director in the client:
BindToRenderStepat Camera+5 forcingCameraType=Scriptableand a_G.DirCF; helpers for Hold/Move/Orbit; toggle HUD ScreenGuis (not TreeGui). Cell→world:X = -134 + 4x, Z = -96 + 4zfor Plot1. Preview framing withscreen_capturebefore recording. - Record: focus Studio,
win+alt+r→ run the shot (execute_luau, < 60 s) →win+alt+r. Stop natural events withdevEvent("")between shots. Trigger events withdevEvent("Thunderstorm" | "MeteorShower" | "BloodMoon" | "CashRain" | "GoldenHour" | "Frost"). Check clips with a timestamped contact sheet and retake bad ones. - Edit in the container: stage clips with
device_stage_files; crop the Studio viewport out of the 2560x1372 capture (delogothe topbar icons,crop=2009:1130:3:156), cut on the beat grid, pop-in captions (Luckiest Guy, white + yellow keyword, thick black stroke, slight tilt), zoom punches, whooshes, end card "EMOTION TYCOON / PLAY NOW". Game audio under the music; loudnorm to -14 LUFS. - Deliver: SendUserFile caps at 30 MB → encode ~4 Mbps 1080p, send it, then
device_commit_filesinto~/Videos. - Audio sources: GitHub CC0 (
Calinou/kenney-interface-sounds,SoundSafari/CC0-1.0-Music); sparse-clone with--filter=blob:none. myinstants/pixabay/freesound are blocked — synthesize whooshes/risers with numpy. - Afterwards: remove
ET_NoSave, stop play.
Finishing a batch
Report per item what changed and how it was verified (playtest with ET_NoSave, no console errors), what you decided
against and why, remind them to publish (and to save the .blend if you touched Blender), then the list of assets
they could draw.