Emotion Tycoon — 工作协议与行动手册
每当用户提到 Emotion Tycoon、树木、工人、投掷器、增益、事件、楼层、存档槽、游戏通行证、突袭、兑换码、管理面板,或要求为其制作图标、粒子、UI、模型、缩略图或宣传视频时使用此手册——即使他们只是描述症状(“树木卡住了”、“粒子看起来太小”、“我卡在 $0 出不来”)。
用户是一位独立 Roblox 开发者(团队为 "Squashed Stuidos",ID 706695552),他会手绘大量美术资源,并对任何看起来像“vibecoded”或 AI 生成的东西非常挑剔。以下所有内容均来自他自己的修正;请视作他的风格准则,而非建议。他经常发送长篇语音输入式请求:将每批请求转换为任务列表,先处理快速 Bug,并在最终报告中回答每一项(包括你决定不执行的项目)。
用户的固定规则
- 尊重用户的编辑。 永远不要覆盖用户手动修改的模型/UI。先读取再写入。
- 不要使用 AI 风格的 UI。 不要使用文本标签/筹码/徽章(如“PASS”、“NEW”、“HOT”),不要使用贴在物体上的光泽渐变药丸,不要使用重叠文本字段的图标,不要使用漂浮的纯文本行来解释事物。应通过布局、轮廓样式、颜色或分组来区分事物。
- 新窗口:克隆一个用户已批准的窗口(如
HUD.FriendModal两列布局、RebirthModal、OfflineModal)并替换其内容,而不是从头创建。从头创建的窗口曾被拒绝,因为“明显是由 AI 制作的”。文本字段 = 凹陷的白色框,带有深色 3px 轮廓,深色文本。 - 玩家拥有的数字外观与现金条类似。 例如,突袭代币 = 在
HUD.Cash旁边克隆一个,加上代币图标,悬停(PC)/点击(手机)显示工具提示。始终使手机端悬停信息可用(点击切换)。 - UI 背景使用真实纹理:
rbxassetid://100839690373358(不能是程序生成的纹理)。 - 优先使用用户手工制作的资源(ID 见下文)。当存在用户自己的资源时,不要生成替代品。
- 每次添加视觉效果后,用简短列表结束回复,列出用户可能绘制的资源来替换占位符。
- Robux 符号是私有使用字符
U+E002。 - 不要凭空想象。 当对 API 或 ID 不确定时,搜索网络/阅读代码。
- 不要打开第二个 Roblox Studio。 计算机使用仅用于 MCP 无法完成的任务(FBX 导入、Game Bar)。
- 永远不要保存用户的 .blend 文件(位于
C:\Users\cosul\Desktop\models_for_roblox\RobloxTycoon.blend);提醒用户按 Ctrl+S 保存。 - Blender 中的 3D 模型: 基于修改器、干净的低多边形、平面着色;齿轮采用
/roblox-r6-armor工具包样式。 - 没有每日奖励(用户更喜欢离线/AFK 收益)。到处保留 "?" 神秘六边形——当 "?" 变成实节点时,在其后面添加新的 "?" 六边形。
- 已决定 / 已拒绝(不要重新提议): 基地保护、跳过重生、“全部升级”(仅每个 NPC 的最大按钮)、化妆品商店、奖杯树(突袭代币保留;通过每日重生前三名 + 每五次重生获得)。天气机器 = 每个地块只能有一个。协同教程:搁置到用户要求为止。
- 永远不要让玩家陷入死胡同。 对成本/树木/重生的任何更改都必须保持通往有效生长线的路径(主要树有
lineCost+rescue充值以及现金树守卫——保持它们正常工作)。
Studio MCP 工作流程
- Studio ID 每次会话都不同——使用
list_roblox_studios获取。 - 编辑数据模型在 Play 模式下不可用。 用户自己进行游戏测试:检查
get_studio_state;当他们在玩时,你仍然可以通过 Server 数据模型读取脚本(game.ServerScriptService.Main.Source)。等待他们(每隔几分钟轮询一次);只有当用户闲置了几分钟时才停止他们的游戏测试,并告知他们。如果用户问“确保东西已保存”:只有在 Edit 模式下编辑才会持久化。 execute_luau在 Client/Server 中有自己的 require 缓存:require(module)返回的是新副本,而不是正在运行的副本(猴子补丁无效)。通过游戏的远程事件访问运行状态(ReplicatedStorage.Remotes.Request:InvokeServer(action, ...),包括admin操作)或实例/属性。要在 Edit 模式下测试 Config 编辑,请require(Config:Clone())。- 脚本编辑:通过
execute_luau使用ScriptEditorService:UpdateSourceAsync,使用string.find(src, old, 1, true)精确查找/替换,并断言匹配是唯一的。使用[==[ ]==]字符串(代码中常包含]])。 UI模块的 start 函数已达到 Luau 的 200 个本地寄存器限制("Out of local registers")。永远不要在那里添加新的顶级本地变量:将新状态/函数放在共享的ext表或do ... end块内。- 要测试罕见状态(例如,满线),请在 Edit 模式下临时更改 Config 常量,进行游戏测试,然后恢复。
- 使用
ET_NoSave进行游戏测试验证:start_stop_play、screen_capture、get_console_output。user_mouse_input的 x/y 是 GUI/屏幕坐标:对于世界点使用WorldToScreenPoint(= viewport y - 58);对于 UI 使用AbsolutePosition。截图按比例缩放(约 0.955 倍于 2011px 视口)。textInput输入到 TextBox 不会到达它——通过远程测试 redeem 类型流程。 - Studio 中的 DataStore 是实时的(API 访问已开启):你在测试期间写入的任何内容(例如测试兑换码)之后必须被删除。
游戏地图(各事物位置)
ReplicatedStorage.Shared.Config— 所有调优项:物品、员工、特权、材料、事件、Robux、RobuxClusters、主题、TreePaths/TreeLayout/RebirthLayout、AURA(谁增强/削弱哪些方块)、CAPACITY_PERKS、MAX_LIVE_CUBES(每投掷器线)/MAX_PLOT_CUBES、天气机器函数(weatherChance、weatherUpgradeCost= 每级下次重生翻倍的份额、weatherRoll、weatherOwned)、突袭定义 + 代币。ReplicatedStorage.Shared.Grid— 单元格数学(20x20 方块,TILE=4)。旋转 r:0 = -Z, 1 = +X, 2 = +Z, 3 = -X。ReplicatedStorage.Shared.VFX— 粒子预设;VFX.burst为每种颜色创建一个发射器。ServerScriptService.Main— 会话、handlers.*用于每个远程动作(包括用于拖拽建造的batch、upgradeWeather、redeemCode、buyRaidToken)、天气机器数据(data.wm、Factory.weatherHook)、救援、心跳循环。pushState可以在批处理期间被保持(s.holdPush)。ServerScriptService.Server.{Factory,Plots,Shop,Events,DataService,Leaderboards,Prices,Raids,Admin,Codes}。Factory:每线的立方体数量(session.lineCount、uncount)、lineCap、投掷器上的LineFull属性、分桶阻挡器检查(保持 O(n),线可容纳 100 个立方体)、Factory.hold用于批处理重建。Admin:仅管理员操作的ops(在线/离线/跨服务器赠送、事件、公告、兑换码)。Codes:DataStoreET_Codes_v1(键codes+uses_<CODE>),种类为 cash/scaled/rp/token/boost,日期,最大使用次数(0 = 无限制)。StarterPlayerScripts.ClientModules.{UI,Build,Cubes,Life,Boards,Aura,Pop}— UI = HUD、树木、模态框、检查面板;Build = 幽灵、通过透明占位符拖拽/批量放置、右键长按删除、移动;Aura = 绿色/红色/黄色方块方块。管理面板 UI:ServerStorage.AdminGui(+AdminClient),仅克隆到管理员的 PlayerGui。- 树画布是
StarterGui.TreeGui.Window.Pan.{Canvas,RebirthCanvas,RobuxCanvas}.Nodes中创作的节点(属性 Q、R、Ring、Path、Mystery)。新节点 = 将该单元格的 "?" 节点重命名/转换(移除Mystery,设置Path)+ 将 ID 添加到Config.TreePaths/RebirthLayout。位置:现金 x = 0.4654 + 0.0691q,y = 0.6062 + 0.0850r + 0.0425q;重生 x = 0.5 + 0.1230q,y = 0.5 + 0.1300r + 0.0650q。 - 仅 Studio 的开发者远程事件:
devEvent、devCash、devRobux、devRobuxRemove、devRobuxReset、devOffline、devTutorial。管理员远程事件(admin、op、...)在 Studio 中为所有者工作(给自己赠送 rp/cash/token)。 - 永远不要意外测试真实存档。 在进行一次性游戏测试前,在 Edit 模式下设置
workspace:SetAttribute("ET_NoSave", true),之后移除它。
已知陷阱(每个都曾咬过我们一次)
- Premium NPC 放置错误会留下“幽灵”方块 →
place在 pcall 内部构建并带有回滚;保持该模式。 - PlayerAdded 会 yield(
Shop.checkPasses、DataStore 加载):每次 yield 后检查会话是否仍然有效,否则已离开的玩家会得到没有所有者的地块重建。PlayerRemoving 会在保存前释放地块。 UIGradient会乘以BackgroundColor3— 带有紫色渐变的青蓝色框架克隆会渲染为深蓝色。当通过渐变重新着色时,将背景设置为白色。- 现金条有一个
BumpUIScale:任何从其 AbsoluteSize 定位的内容都必须除以该比例。 - 在 Build 模式中,鼠标右键 = 长按删除;相机平移为鼠标中键 / WASD。
- 树拖拽开始必须使用
UIS.InputBegan(按钮按下永远不会到达win.InputBegan)。 - 楼层主题纹理应放在地板之上(Texture 实例);永远不要改变地板的 Material。
- 用户粒子表为 2x2 翻页书,带有小形状 → 缩放大小约 2–2.5 倍;多颜色 = 多个发射器。
- 新上传的纹理可能暂时模糊(Roblox 处理中)。
- 高阶投掷器每阶段需要大量工作;弱线售价约 $1(空立方体价值)。
- 图片:
upload_image从本地 HTTP 服务器工作(例如http://127.0.0.1:8765/<file>)。 - FBX 管线: 从 Blender 导出,使用
use_selection=True, object_types={'MESH'}, apply_unit_scale=True, mesh_smooth_type='FACE'到%LOCALAPPDATA%\Temp\et_export\;通过计算机使用导入(Asset Manager → Import → 输入路径 → Import),最终位于workspace.<FbxName>。导入器镜像 X 轴:使用CFrame.new(-x_b, z_b, y_b)从 Blender 坐标放置部件。预览渲染:临时 "ET_Preview" 场景 → 分阶段图像。 - 游戏中不允许外部链接:Discord/群组放在游戏页面的 Social Links;游戏中仅可使用
GroupService:PromptJoinAsync(groupId)的“加入群组”按钮。
商业化布局(当前)
- Robux 商店 = 你可以在其间平移的独立岛屿(
Config.RobuxClusters:游戏通行证、高级工人、现金、增益和事件)。添加通行证 = 将其 ID 添加到岛屿的items+ 在RobuxCanvas.Nodes中添加一个六边形。 - 通行证和产品通过岛屿和轮廓动画区分,从不使用标签。
- 价格实时获取(
Server.Prices→ReplicatedStorage属性RobuxPrices)。 - 通行证 ID:HypeQueen 2026442663, DiamondWorker 2026394625, PassMidas 2025590666, PassLuck 2025848628, PassDrop 2025464639, PassVIP 2026922652, GoldenRobot 2025374681, LayoutSlot3 2026652648, LayoutSlot4 2026010654, Pass2x 2027138654。
- 产品 ID: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。
- 楼层是免费的重生奖励,在设置中选择。Factory 存档:2 个免费槽位,槽位 3–4 为通行证。
- 后期玩家拥有六位数(sextillions)和 30+ 次重生:将后期内容定价为
Config.rebirthCost的一部分(永远缩放到无限大),而不是固定数字;出于同样原因,兑换码默认设置为“下次重生的百分比”。
用户的资源
图标: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(线满标志), backpack_cubes 84466301181838 / crate_cubes 108346564955404 / chest_cubes 131689000211065(容量特权)。
楼层:ocean_lights 138556700370722, holy 105026190310831, pink 83692624195325, pink_green 136148045549462, redx 124121848293779.
粒子(2x2 表):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"](列出 Decals 获取 ID):有用的包括 — Down arrow 17368169201, Codes 17368032566, MultiGifts 15402969720, Expand 17368183719, Click 17260727409, Rocket 16670799841, Box 17368122337, Crate 17368402884。CubePets 17368391613 是一只狗——永远不要将其用于非宠物物体。
宣传视频配方(全自动,在首次批准后无需用户点击)
- 一次性批准: 使用系统键组合访问 Roblox Studio 和 Game Bar,以及
~/Videos文件夹访问权限(Game Bar 保存到Videos\Captures)。 - 展示状态: 设置
ET_NoSave,开始游戏测试,然后通过 Request 远程事件:devCash,解锁每个现金树节点(循环unlock直到没有进展),清除布局,建造 4 条线(投掷器在 x=1 r=1,传送带 x=2..17,售卖器在 x=18;工人分布在两侧面向传送带)。使用 Dropper2–4 以使立方体实际填充并以实际数字出售。 - 客户端导演:
BindToRenderStep在 Camera+5 强制CameraType=Scriptable和一个_G.DirCF;帮助函数用于 Hold/Move/Orbit;切换 HUD ScreenGuis(不是 TreeGui)。单元格→世界:对于 Plot1,X = -134 + 4x, Z = -96 + 4z。录制前使用screen_capture预览取景。 - 录制: 聚焦 Studio,
win+alt+r→ 运行镜头(execute_luau,< 60 秒)→win+alt+r。使用devEvent("")在镜头之间停止自然事件。使用devEvent("Thunderstorm" | "MeteorShower" | "BloodMoon" | "CashRain" | "GoldenHour" | "Frost")触发事件。使用带时间戳的联系表检查片段并重拍不好的。 -
…
[为翻译截断]