{"id":604,"date":"2026-06-22T06:29:07","date_gmt":"2026-06-22T06:29:07","guid":{"rendered":"https:\/\/alffarmtale.top\/?p=604"},"modified":"2026-06-22T06:30:00","modified_gmt":"2026-06-22T06:30:00","slug":"agents","status":"publish","type":"post","link":"https:\/\/alffarmtale.top\/?p=604","title":{"rendered":"AGENTS.md"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">AlfFarmTale \u9879\u76ee\u4e13\u5c5e\u7684\u300c\u5c0f\u6284\u672c\u300d\u3002AI Agent \/ \u65b0\u4eba \/ \u672a\u6765\u7684\u4f60\u8fdb\u9879\u76ee\u65f6\uff0c\u5148\u8bfb\u8fd9\u4e00\u4efd\u3002<br>\u6700\u540e\u66f4\u65b0\uff1a2026-06-21\uff08\u7b2c\u4e8c\u8f6e\u6574\u7406\uff1a\u8865\u5168 npc4001~4003\u3001\u4fee\u6b63 ID \u6bb5\u3001\u8865 MapCapture \u8def\u5f84\u3001\u6269\u5145 building\/hold_effect \u5217\u8868\u3001\u4fee\u6b63 wood bug \u8bf4\u660e\uff09<\/h1>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">0. \u9879\u76ee\u901f\u89c8<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u5f15\u64ce<\/strong>\uff1aGodot 4.5 Forward Plus\uff08Web \u7aef\u5207\u5230 GL Compatibility\uff09<\/li>\n\n\n\n<li><strong>viewport<\/strong>\uff1a480\u00d7270 \u50cf\u7d20\u98ce\uff0cwindow 1440\u00d7810\uff0c<code>stretch\/mode = canvas_items<\/code><\/li>\n\n\n\n<li><strong>\u4e3b\u573a\u666f<\/strong>\uff1a<code>res:\/\/scenes\/main\/main.tscn<\/code>\uff08\u6807\u9898\/\u5b58\u6863\u83dc\u5355\uff09\u2192 \u70b9 NewGame \/ Continue \/ LoadGame \u5207\u5230 <code>Game<\/code>\uff08<code>scenes\/game\/game.tscn<\/code>\uff09<\/li>\n\n\n\n<li><strong>\u5bfc\u51fa\u5e73\u53f0<\/strong>\uff1a\u4ec5 Web\uff08<code>export_presets.cfg<\/code> \u4e00\u6761 web preset\uff09<\/li>\n\n\n\n<li><strong>\u5173\u952e Addons<\/strong>\uff1aDialogic 2\uff08\u5bf9\u8bdd\uff09\u3001PhantomCamera 2D\uff08\u76f8\u673a\uff09\u3001LimboAI\uff08NPC \u884c\u4e3a\u6811\uff09\u3001imgui-godot\uff08\u7f16\u8f91\u5668\u8c03\u8bd5\uff0c\u5df2\u5e9f\u5f03\uff09\u3001awesome_custom_cursor\u3001inventory_editor<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Inventory ID \u4f53\u7cfb\uff08\u6309 <code>Inventory.InventoryType<\/code> enum \u7d22\u5f15\uff09<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u6ce8\u610f<\/strong>\uff1aenum \u6ce8\u91ca\u4e0e\u5b9e\u9645 .tres \u6570\u636e\u6709\u51fa\u5165\uff0c<strong>\u5b9e\u9645\u6570\u636e\u4ee5\u4e0b\u8868\u300c\u5df2\u7528\u300d\u5217\u4e3a\u51c6<\/strong>\u3002<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Enum \u7d22\u5f15<\/th><th>\u5343\u4f4d ID \u6bb5<\/th><th>\u6ce8\u91ca<\/th><th>\u5b9e\u9645 .tres \u6570\u636e<\/th><th>.tres \u6570<\/th><\/tr><\/thead><tbody><tr><td>Weapon (0)<\/td><td>1000<\/td><td>\u6b66\u5668<\/td><td>1001 sword<\/td><td>1<\/td><\/tr><tr><td>Armor (1)<\/td><td>2000<\/td><td>\u9632\u5177<\/td><td><strong>\u65e0<\/strong><\/td><td>0<\/td><\/tr><tr><td>Material (2)<\/td><td>3000<\/td><td>\u6750\u6599<\/td><td><strong>id \u6bb5\u6709\uff0c\u4f46\u53ea\u6709 medicine\/wood.tres \u5360\u4f4d\uff08\u89c1 \u00a713 bug\uff09<\/strong><\/td><td>0<\/td><\/tr><tr><td>Seed (3)<\/td><td>4000<\/td><td>\u79cd\u5b50<\/td><td>4001~4007<\/td><td>7<\/td><\/tr><tr><td>Food (4)<\/td><td>5000<\/td><td>\u98df\u7269<\/td><td>5000~5007<\/td><td>8<\/td><\/tr><tr><td>Medicine (5)<\/td><td>6000<\/td><td>\u836f\u54c1<\/td><td>\u53ea\u6709 wood.tres\uff08id=3001\uff0c\u8def\u5f84\u4e0e type \u90fd\u4e0d\u4e00\u81f4\uff0c\u89c1 \u00a713 bug\uff09<\/td><td>1\uff08\u9519\u4f4d\uff09<\/td><\/tr><tr><td>Tool (6)<\/td><td>7000<\/td><td>\u5de5\u5177<\/td><td>7001 hoe \/ 7002 sprinkler \/ 7003 axe<\/td><td>3<\/td><\/tr><tr><td>Crop (7)<\/td><td>8000<\/td><td>\u4f5c\u7269<\/td><td><strong>enum \u6ce8\u91ca\u8bf4&#8221;\u4f5c\u7269 8000&#8243;\uff0c\u4f46\u5b9e\u9645\u6240\u6709 id=8001~8095 \u7684\u7269\u54c1 .tres \u90fd\u662f type=8 (Building)<\/strong><\/td><td>0<\/td><\/tr><tr><td>Building (8)<\/td><td>9000<\/td><td>\u5efa\u7b51<\/td><td>\u5b9e\u9645\u7528 8001~8095 \u6bb5\uff08type=8\uff09\uff0c\u5171 <strong>92 \u4e2a .tres<\/strong>\uff08id 8061\/8062\/8063 \u7f3a\u53f7\uff09<\/td><td>92<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>\u8bbe\u8ba1\u4e0a\u7684\u4e0d\u4e00\u81f4<\/strong>\uff1a<code>inventory.gd<\/code> \u6ce8\u91ca\u8bf4&#8221;\u4f5c\u7269 8000 \/ \u5efa\u7b51 9000&#8243;\uff0c\u4f46 .tres \u5b9e\u9645\u5168\u7528 8000 \u6bb5\uff08type=8 = Building\uff09\u3002<strong>\u6539\u4efb\u4f55\u6d89\u53ca building \u7684\u4ee3\u7801\u524d\uff0c\u5148\u786e\u8ba4 id \u6bb5\u662f 8000 \u4e0d\u662f 9000<\/strong>\u3002\u8be6\u89c1 \u00a713 <code>BuildingResource.BuildingType<\/code> enum \u5df2\u5e9f\u5f03\u8bf4\u660e\u3002<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">\u5b63\u8282<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>TimeRecord.Season { Spring, Summer, Fall, Winter }<\/code><\/li>\n\n\n\n<li>\u6708\u4efd \u2192 \u5b63\u8282\u6620\u5c04\u5199\u5728 <code>time_record.gd<\/code> \u7684 <code>SEASONS<\/code> \u5e38\u91cf\u91cc<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">NPC \u7c7b\u578b\uff08<code>NPC.NpcType<\/code> enum\uff09<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u503c<\/th><th>\u7528\u9014<\/th><th>\u4f4d\u7f6e<\/th><th>BT \u6811<\/th><\/tr><\/thead><tbody><tr><td><code>wuning<\/code><\/td><td>\u5267\u60c5 NPC\uff08\u5267\u60c5\u5185\u5f15\u7528\uff0c\u65e0\u811a\u672c\u7c7b\uff09<\/td><td>\u2014<\/td><td>\u2014<\/td><\/tr><tr><td><code>npc1001<\/code><\/td><td>\u8239\u592b\uff08silver_mist \u2194 village_01 \u8f6c\u79fb\uff09<\/td><td><code>compoents\/npc\/npc1001\/<\/code><\/td><td><code>ai\/trees\/npc1001.tres<\/code><\/td><\/tr><tr><td><code>npc2001<\/code><\/td><td>\u5e97\u4e3b\uff08village_01\uff09<\/td><td><code>compoents\/npc\/npc2001\/<\/code><\/td><td><code>ai\/trees\/npc2001.tres<\/code><\/td><\/tr><tr><td><code>npc4001<\/code><\/td><td>\u5bb6\u5177\u5e97\u4e3b\uff08silver_mist\uff09<\/td><td><code>compoents\/npc\/npc4001\/<\/code><\/td><td><code>ai\/trees\/npc4001.tres<\/code><\/td><\/tr><tr><td><code>npc4002<\/code><\/td><td>\u98df\u6750\u79cd\u5b50\u5e97\u4e3b\uff08silver_mist\uff09<\/td><td><code>compoents\/npc\/npc4002\/<\/code><\/td><td><code>ai\/trees\/npc4002.tres<\/code><\/td><\/tr><tr><td><code>npc4003<\/code><\/td><td>\u6b66\u5668\u6742\u8d27\u5e97\u4e3b\uff08silver_mist\uff09<\/td><td><code>compoents\/npc\/npc4003\/<\/code><\/td><td><code>ai\/trees\/npc4003.tres<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">\u26a0\ufe0f <code>NPC.NPC_TYPE<\/code> \u5b57\u5178\uff08character.gd \u7684 <code>to_shop<\/code> \u8d70 <code>NPC.NPC_TYPE.get(npc)<\/code>\uff09\u5fc5\u987b\u542b\u6bcf\u4e2a <code>NpcType<\/code> \u503c\uff0c\u5426\u5219 <code>to_shop<\/code> \u4f1a push_error\u3002\u65b0\u589e NPC \u52a1\u5fc5\u540c\u6b65\u3002<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">1. \u4f53\u529b\u7cfb\u7edf\uff08energy\uff09<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u4f53\u529b\u5206\u4e24\u79cd\u6765\u6e90\uff0c<strong>\u53ea\u80fd\u8ffd\u56de\u5176\u4e2d\u4e00\u79cd<\/strong>\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u6765\u6e90<\/th><th>\u884c\u4e3a<\/th><th>\u6301\u4e45\u5316\u5b57\u6bb5<\/th><\/tr><\/thead><tbody><tr><td>\u8dd1\u6b65\uff08\u6309\u4f4f Shift\uff09<\/td><td>\u6d88\u8017\u53ef\u81ea\u7136\u56de\u590d<\/td><td><code>energy_current<\/code> \u76f4\u63a5\u64cd\u4f5c<\/td><\/tr><tr><td>\u5de5\u5177\u64cd\u4f5c\uff08\u9504\u5730\/\u6d47\u6c34\/\u780d\u6811\/\u64ad\u79cd\/\u5efa\u9020\uff09<\/td><td>\u6d88\u8017<strong>\u6c38\u4e45\u6263\u9664<\/strong>\uff0c\u4e0d\u53ef\u81ea\u7136\u56de\u590d<\/td><td><code>energy_floor<\/code> \u7d2f\u52a0<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>CharacterResource.energy_max = 40<\/code>\u3001<code>energy_current = 40.0<\/code>\u3001<code>energy_floor = 0.0<\/code><\/li>\n\n\n\n<li>\u8dd1\u6b65\u56de\u590d\u5c01\u9876\uff1a<code>min(energy_max - energy_floor, current + RECOVER_RATE)<\/code><\/li>\n\n\n\n<li>\u8dd1\u6b65\u673a\u5236\u8be6\u7ec6\u53c2\u6570\u89c1 <code>compoents\/character\/character.gd:9-18<\/code>\uff08RUN_COST_PER_SEC \u7b49\u5e38\u91cf\uff09<\/li>\n\n\n\n<li>\u5598\u6c14\u671f\uff1a\u4f53\u529b\u5f52\u96f6\u540e 2 \u79d2\u5185 Shift \u65e0\u6548\uff08<code>_panting_timer<\/code>\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u4f53\u529b\u5f52\u96f6\u62e6\u622a\uff082026-06\uff09<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><code>energy_current &lt;= 0.0<\/code> \u65f6\u7981\u6b62\u6240\u6709\u6d88\u8017\u4f53\u529b\u7684\u5de5\u5177\u64cd\u4f5c\uff08\u9504\u5730\/\u6d47\u6c34\/\u780d\u6811\uff09\uff0c\u5e76\u53d6\u6d88 range \u663e\u793a\u3002<\/strong> \u89e6\u53d1&#8221;\u7d2f\u762b&#8221;\u5bf9\u8bdd\u63d0\u793a\u73a9\u5bb6\u5403\u4e1c\u897f\/\u7761\u89c9\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u5224\u5b9a\u9608\u503c<\/strong> <code>&lt;= 0.0<\/code>\uff1a\u4e0e <code>character.gd:99<\/code> \u89e6\u53d1\u5598\u6c14\u671f\u7684\u8fb9\u754c\u5bf9\u9f50\uff0c\u4e0e <code>consume_food<\/code> \u6ee1\u4f53\u529b\u5b88\u536b\u98ce\u683c\u4e00\u81f4<\/li>\n\n\n\n<li><strong>\u5355\u70b9\u62e6\u622a<\/strong>\uff1a<code>range_prompt.deal_hold_action()<\/code> \u5728\u8c03 <code>play_effect<\/code> \u524d\u5b88\u536b\u4e00\u6b21\u5373\u53ef\uff0c7001\/7002\/7003 \u4e00\u884c\u4e0d\u7528\u6539<\/li>\n\n\n\n<li><strong><code>HoldEffectResource.consumes_energy() -&gt; bool<\/code><\/strong>\uff1a\u65b0\u865a\u65b9\u6cd5\uff0c\u9ed8\u8ba4 <code>false<\/code>\uff1b\u9504\u5730\uff087001\uff09\/\u6d47\u6c34\uff087002\uff09\/\u780d\u6811\uff087003\uff09override \u8fd4\u56de <code>true<\/code>\u3002\u79cd\u5b50\/\u5efa\u9020\/\u5251\/\u98df\u7269\u9ed8\u8ba4 false\uff0c\u4e0d\u88ab\u62e6\u622a<\/li>\n\n\n\n<li><strong>\u672a\u6765\u52a0\u65b0\u6d88\u8017\u5de5\u5177<\/strong>\uff08\u5982 hammer \/ pickaxe\uff09\uff1a\u53ea\u9700 override <code>consumes_energy() -&gt; true<\/code>\uff0c\u4e0d\u7528\u6539 range_prompt<\/li>\n\n\n\n<li><strong><code>range_prompt.update_visible()<\/code><\/strong> \u52a0\u5206\u652f\uff1a\u4f53\u529b &lt;= 0 \u4e14 <code>current_effect.consumes_energy()<\/code> \u2192 <code>visible = false<\/code><\/li>\n\n\n\n<li><strong><code>range_prompt.deal_hold_action()<\/code><\/strong> \u52a0\u5b88\u536b\uff1a\u4f53\u529b &lt;= 0 \u4e14 <code>current_effect.consumes_energy()<\/code> \u2192 <code>return<\/code>\uff08\u4e0d\u64ad\u52a8\u753b\u3001\u4e0d add_farmland \/ to_watering \/ to_tool \/ breakable.hit\uff09<\/li>\n\n\n\n<li><strong>\u629b\u5149\uff08hold.gd:update_effect\uff09<\/strong>\uff1a\u5207\u5de5\u5177\u65f6\u82e5 <code>current_effect.consumes_energy() &amp;&amp; current &lt;= 0<\/code>\uff0c<strong>\u4e0d\u8c03<\/strong> <code>show_range<\/code>\uff0c\u907f\u514d\u5207\u5230\u5de5\u5177\u77ac\u95f4\u95ea\u4e00\u5e27 range<\/li>\n\n\n\n<li><strong><code>statusinfo._on_consume_energy*<\/code> \u7684 <code>if current &gt; 0<\/code> \u5b88\u536b\u4fdd\u7559<\/strong>\uff1a\u4f5c\u4e3a last-line defense \u9632 bug\uff0c\u4e0d\u4f9d\u8d56\u5b83\u505a\u4e3b\u62e6\u622a\uff08\u5b83\u53ea\u80fd\u6321&#8221;\u6263\u80fd\u91cf&#8221;\uff0c\u6321\u4e0d\u4f4f&#8221;\u52a8\u4f5c&#8221;\uff09<\/li>\n\n\n\n<li><strong>\u5598\u6c14\u671f vs \u5de5\u5177\u62e6\u622a\u72ec\u7acb<\/strong>\uff1a\u5598\u6c14\u671f\u53ea\u6321 Shift \u8dd1\u6b65\uff08<code>character.gd:138<\/code>\uff09\uff0c\u5de5\u5177\u62e6\u622a\u662f\u53e6\u4e00\u6761\u72ec\u7acb\u901a\u9053<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u7d2f\u762b\u5bf9\u8bdd\uff08Alf_stamina_deplete\uff0c2026-06\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>timeline<\/strong>\uff1a<code>res:\/\/dialogic\/timeline\/Alf_stamina_deplete.dtl<\/code>\uff08bubble \u98ce\u683c\uff0c\u4e24\u884c\u63d0\u793a\uff1a\u56db\u80a2\u8f6f\u8f6f\u7684 + \u809a\u5b50\u7a7a\u7a7a\u7684\uff09<\/li>\n\n\n\n<li><strong>\u89e6\u53d1\u70b9<\/strong>\uff1a<code>statusinfo.gd<\/code> \u7684 <code>_process<\/code> \u91cc\u68c0\u6d4b <code>_last_energy &gt; 0.0 &amp;&amp; energy_current &lt;= 0.0<\/code> \u8fb9\u6cbf<\/li>\n\n\n\n<li><strong>\u89e6\u53d1\u6a21\u5f0f<\/strong>\uff1a\u4ece\u6b63\u6570\u8dcc\u5230 &lt;= 0 \u90a3\u4e00\u5e27\u89e6\u53d1\u4e00\u6b21\uff1b\u4e4b\u540e\u5373\u4f7f current \u4ecd &lt;= 0 \u4e5f\u4e0d\u518d\u89e6\u53d1\uff1b\u8981\u7b49 current \u91cd\u65b0 &gt; 0 \u540e\u518d\u6b21\u8dcc\u5230 0 \u624d\u518d\u89e6\u53d1\uff08\u907f\u514d\u5598\u6c14\u671f\u53cd\u590d\u5f39\uff09<\/li>\n\n\n\n<li><strong>\u9996\u6b21\u5e27\u8df3\u8fc7<\/strong>\uff1a<code>_is_first_frame<\/code> \u5b88\u536b\u907f\u514d\u52a0\u8f7d\u4e00\u4e2a <code>current=0<\/code> \u7684\u5b58\u6863\u65f6\u8bef\u5f39<\/li>\n\n\n\n<li><strong>\u8c03\u7528\u6a21\u5f0f<\/strong>\uff1a\u8ddf wuninghouse_cutscene \u7b49\u5267\u60c5\u811a\u672c\u4e00\u81f4 \u2014 <code>Dialogic.start()<\/code> + <code>character.on_dialogue_timeline_started()<\/code>\uff08\u8bbe <code>is_dialogue=true<\/code>\uff09+ <code>await Dialogic.timeline_ended<\/code> + <code>character.on_dialogue_timeline_ended()<\/code><\/li>\n\n\n\n<li><strong>\u5bf9\u8bdd\u671f\u95f4\u4e0d\u80fd\u64cd\u4f5c<\/strong>\uff1a\u56e0 <code>is_dialogue=true<\/code>\uff0c<code>character.gd:138<\/code> \u7684 direction \u88ab\u6e05\u7a7a\uff08sprint \u5931\u6548\uff09\u3001<code>distribute_input<\/code> \u7684 right_mouse\/left_mouse \u4e0d\u89e6\u53d1\uff1b\u73a9\u5bb6\u770b\u5b8c\u5bf9\u8bdd\u518d\u6062\u590d<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u80fd\u91cf\u6761 UI\uff082026-06\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u65e7\u7248\uff1a\u4f53\u529b &lt;= 0 \u65f6 <code>EnergyInner.visible = false<\/code>\uff08\u5916\u6846\u5728\u3001\u5185\u6846\u6574\u4e2a\u9690\u85cf\uff09\uff0c\u73a9\u5bb6\u770b\u4e0d\u5230&#8221;\u7d2f\u762b&#8221;\u72b6\u6001<\/li>\n\n\n\n<li>\u65b0\u7248\uff1a\u59cb\u7ec8\u663e\u793a <code>EnergyInner<\/code>\uff0cwidth \u6309 <code>current\/max<\/code> \u6491\u5f00\uff1b<code>&lt;= 0<\/code> \u65f6 <code>modulate = Color(0.55, 0.35, 0.35)<\/code>\uff08\u6697\u7ea2\u8272\uff09\u63d0\u793a\u73a9\u5bb6\u6ca1\u529b\u6c14\u4e86<\/li>\n\n\n\n<li>\u4ecd\u5728 <code>compoents\/character\/children\/attribute\/children\/statusinfo\/statusinfo.gd<\/code> \u91cc\u7ef4\u62a4<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><code>character_resource.gd:energy_floor<\/code> \u9ed8\u8ba4\u503c\u5751\uff082026-06 \u4fee\u590d\uff09<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u5386\u53f2 bug<\/strong>\uff1a<code>structs\/character_resource.gd<\/code> \u7684 <code>energy_floor<\/code> \u539f\u672c\u9ed8\u8ba4\u503c\u662f <code>1<\/code>\uff08\u4e0d\u662f <code>0.0<\/code>\uff09\uff0c\u540c\u65f6 <code>resources\/character_resource.tres<\/code> \u52a0\u8f7d\u65f6\u672a\u58f0\u660e energy \u4e09\u4e2a\u5b57\u6bb5 \u2192 \u5168\u90e8\u8d70\u9ed8\u8ba4 \u2192 \u5f00\u5c40\u5c31\u88ab <code>update_stamina<\/code> 1 \u79d2\u540e clamp \u5230 <code>ceiling = max - floor = 40 - 1 = 39<\/code>\u3002UI \u7528 <code>current \/ max = 39\/40 = 0.975<\/code> \u663e\u793a\uff0c\u73a9\u5bb6\u770b\u5230\u80fd\u91cf\u6761<strong>\u5dee\u4e00\u70b9\u70b9\u4e0d\u6ee1<\/strong>\uff0c\u4ee5\u4e3a\u662f bug\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u4fee\u590d\uff082026-06\uff09<\/strong>\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>energy_floor<\/code> \u9ed8\u8ba4\u503c\u6539\u6210 <code>0.0<\/code><\/li>\n\n\n\n<li><code>resources\/character_resource.tres<\/code> \u663e\u5f0f\u58f0\u660e <code>energy_max = 40<\/code> \/ <code>energy_current = 40.0<\/code> \/ <code>energy_floor = 0.0<\/code>\uff08\u4e4b\u524d\u4e09\u4e2a\u5b57\u6bb5\u5168\u9760\u4ee3\u7801\u9ed8\u8ba4\uff0c\u52a0\u8f7d\u987a\u5e8f\u654f\u611f\uff09<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u4e3a\u4ec0\u4e48\u662f floor \u6a21\u578b\u8bbe\u8ba1\u7f3a\u9677<\/strong>\uff1a<code>energy_floor<\/code> \u8868\u8fbe&#8221;\u5df2\u6c38\u4e45\u6263\u9664\u7684\u4f53\u529b&#8221;\uff08AGENTS.md \u00a71\uff09\uff0c\u5f00\u5c40\u5e94\u8be5\u662f 0\uff08\u73a9\u5bb6\u6ca1\u505a\u8fc7\u4efb\u4f55\u6d88\u8017\u52a8\u4f5c\uff09\u3002\u9ed8\u8ba4 1 \u610f\u5473\u7740\u73a9\u5bb6\u51ed\u7a7a\u88ab\u6263\u4e86 1 \u70b9\u4f53\u529b\u2014\u2014\u6ca1\u6e38\u620f\u903b\u8f91\u652f\u6491\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Web \u6a21\u5f0f\u989d\u5916\u6ce8\u610f<\/strong>\uff1a<code>WebSaveAdapter.SEED_RUNTIME_PATHS:29<\/code> \u628a <code>character_resource.tres<\/code> cold-start \u62f7\u5230 <code>user:\/\/runtime_state\/<\/code> \u505a\u955c\u50cf\uff0c<strong>\u53ea seed \u4e00\u6b21<\/strong>\u3002\u6539\u6e90 .tres \u540e\u65e7\u955c\u50cf\u4ecd\u662f floor=1\uff0c\u5fc5\u987b\u8c03 <code>WebSaveAdapter.reset_runtime_state()<\/code> \u6e05\u6389\u955c\u50cf\u624d\u80fd\u8ba9\u6539\u52a8\u751f\u6548\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u672a\u6765\u52a0\u300c\u98df\u7269\/\u7761\u89c9\u6062\u590d\u4f53\u529b\u300d\u65f6<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u4e0d\u8981<\/strong>\u76f4\u63a5 +<code>energy_current<\/code><\/li>\n\n\n\n<li>\u8c03 <code>energy_floor = max(0, energy_floor - N)<\/code>\uff0c\u8ba9\u300c\u81ea\u7136\u56de\u590d\u4e0a\u9650\u300d\u81ea\u52a8\u4e0a\u79fb<\/li>\n\n\n\n<li>\u8fd9\u6837\u4e0e\u73b0\u6709\u5c01\u9876\u903b\u8f91\u4e00\u81f4\uff0cUI \u4e0d\u4f1a\u8df3\u503c<\/li>\n\n\n\n<li><strong>\u5b8c\u6574\u8303\u5f0f<\/strong>\uff08<code>character.gd:consume_food<\/code>\uff0c2026-06 \u5b9e\u73b0\uff09\uff1a<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><code>energy_floor = max(0, energy_floor - restore_value)<\/code><\/li>\n\n\n\n<li><code>ceiling = energy_max - energy_floor<\/code>\uff08\u65b0\u5c01\u9876\uff09<\/li>\n\n\n\n<li><code>energy_current = min(ceiling, energy_current + restore_value)<\/code>\uff08\u7acb\u523b\u62c9\u5230\u65b0\u5c01\u9876\uff0c\u7ed9\u73a9\u5bb6\u5373\u65f6\u53cd\u9988\uff09<\/li>\n\n\n\n<li>\u6263 1 \u4e2a\u7269\u54c1\uff0ccount \u2192 0 \u65f6 <code>slot.current.clear() + slot.update_display()<\/code><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u4e0d\u53d8\u91cf<\/strong>\uff1a<code>energy_current \u2264 energy_max - energy_floor<\/code>\uff08\u5373 current \u2264 ceiling\uff09\u3002floor \u6a21\u578b\u4efb\u4f55\u64cd\u4f5c\u90fd\u7ef4\u6301\u8fd9\u4e2a<\/li>\n\n\n\n<li><strong>\u6ee1\u4f53\u529b\u5224\u5b9a<\/strong>\uff1a<code>current &gt;= ceiling<\/code>\uff08<strong>\u4e0d\u662f<\/strong> <code>current == max<\/code>\uff09\u3002floor &gt; 0 \u65f6 current \u6c38\u8fdc\u5230\u4e0d\u4e86 max<\/li>\n\n\n\n<li><strong>\u6ee1\u4f53\u529b\u5b88\u536b<\/strong>\uff08<code>consume_food:411-419<\/code>\uff0c<strong>2026-06 \u4fee\u590d<\/strong>\uff09\uff1a\u65e7\u7248\u7528 <code>if current &gt;= ceiling: return<\/code> \u5728 <code>floor &gt; 0 \/ current = ceiling<\/code> \u65f6\u9519\u8bef return\uff08\u73a9\u5bb6\u89c6\u89c9\u770b\u5230\u80fd\u91cf\u6761 12.5% \u89c9\u5f97&#8221;\u5feb\u6ca1\u7535&#8221;\uff0c\u53f3\u952e pumpkin \u5374\u88ab\u5b88\u536b\u62e6\u6389\uff0c\u7269\u54c1\u4e5f\u4e0d\u6263\uff0c\u4f53\u9a8c\u4e0a\u662f&#8221;\u5403\u4e1c\u897f\u6ca1\u53cd\u5e94&#8221;\uff09\u3002\u65b0\u7248\u6539\u4e3a\u9884\u6d4b\u7b97\u6cd5\uff1a<strong>\u5403\u5b8c\u4e0d\u80fd\u6da8 current \u5c31\u4e0d\u5403<\/strong>\u3002\u8ba1\u7b97 <code>future_floor \/ future_ceiling \/ future_current = min(future_ceiling, current + restore)<\/code>\uff0c<code>if future_current &lt;= current: return<\/code>\u3002\u6db5\u76d6\uff1a<\/li>\n\n\n\n<li><code>floor=0 \/ current=ceiling=max<\/code>\uff1a\u5403\u5b8c future_current == current \u2192 return \u2192 \u4e0d\u5403\uff08\u6ee1 max\uff0c\u6ca1\u6536\u76ca\uff09<\/li>\n\n\n\n<li><code>floor=35 \/ current=5 \/ ceiling=5<\/code>\uff1a\u5403\u5b8c future_floor=25 \/ future_ceiling=15 \/ future_current=15 &gt; 5 \u2192 \u4e0d return \u2192 \u5403 \u2192 current \u6da8\u5230 15 \u2713<\/li>\n\n\n\n<li><code>floor=40 \/ current=0 \/ ceiling=0<\/code>\uff08\u7d2f\u762b\u5bf9\u8bdd\u671f\u95f4\uff09\uff1a\u5403\u5b8c future_floor=30 \/ future_ceiling=10 \/ future_current=10 &gt; 0 \u2192 \u4e0d return \u2192 \u5403 \u2192 current \u6da8\u5230 10 \u2713<\/li>\n\n\n\n<li><strong>\u6ce8\u610f<\/strong>\uff1a\u5bf9\u8bdd\u671f\u95f4 <code>is_dialogue=true<\/code>\uff0c<code>character.gd:144<\/code> \u7684 right_mouse \u5165\u53e3\u88ab <code>!is_dialogue<\/code> \u5b88\u536b\u62e6\u6389\uff0c<strong>\u5bf9\u8bdd\u671f\u95f4\u4e0d\u80fd\u5403\u4e1c\u897f<\/strong>\u2014\u2014\u5fc5\u987b\u7b49 <code>Dialogic.timeline_ended<\/code> \u540e\u624d\u80fd\u53f3\u952e<\/li>\n\n\n\n<li><strong>\u8f85\u52a9\u65b9\u6cd5<\/strong>\uff1a<\/li>\n\n\n\n<li><code>character.get_energy_ceiling() -&gt; float<\/code> \u2014 \u8fd4\u56de\u5f53\u524d\u5c01\u9876 <code>max - floor<\/code><\/li>\n\n\n\n<li><code>character.clamp_energy_to_ceiling()<\/code> \u2014 \u628a current \u5f3a\u5236 \u2264 ceiling\uff08\u9632 stale current \u6ea2\u51fa\uff09<\/li>\n\n\n\n<li><strong>\u672a\u6765\u52a0 max \u53d8\u5316\u65f6<\/strong>\uff08\u63d0\u5347\/\u964d\u4f4e max \u7684 buff \u6216\u5347\u7ea7\uff09\uff1a<strong>\u5148\u8c03 <code>clamp_energy_to_ceiling()<\/code> \u518d\u6539 max<\/strong>\uff0c\u5426\u5219 max \u964d\u540e current \u53ef\u80fd &gt; ceiling \u6ea2\u51fa<\/li>\n\n\n\n<li><strong>\u6062\u590d\u91cf\u5199\u5728 Inventory \u4e0a<\/strong>\uff1a<code>@export var restore_value: int = 0<\/code>\uff0c\u8ddf <code>terrain_id<\/code> \u540c\u6b3e\uff08AGENTS.md \u00a76\uff09\u3002Food\/Medicine \u7c7b\u578b\u81ea\u5df1\u586b\u503c\uff0c\u5176\u4ed6\u7c7b\u578b\u4fdd\u6301 0<\/li>\n\n\n\n<li><strong>\u5165\u53e3<\/strong>\uff1a\u624b\u6301 Food \u7c7b\u7269\u54c1\u6309\u9f20\u6807\u53f3\u952e\uff08<code>right_mouse<\/code> action\uff09\uff0c<code>character.gd:distribute_input<\/code> \u8c03 <code>consume_food()<\/code>\u3002\u95e8\u7981\u540c walk\uff1a<code>is_interfact_state() &amp;&amp; !is_dialogue &amp;&amp; !LoadingManager.is_loading &amp;&amp; !UtilsManager.is_shop<\/code><\/li>\n\n\n\n<li><strong>food \u73b0\u72b6<\/strong>\uff08<code>resources\/inventory\/food\/*.tres<\/code>\uff0c\u5df2\u586b restore_value\uff09\uff1a<\/li>\n\n\n\n<li>apple 5 \/ carrot 5 \/ tomato 6 \/ eggplant 6 \/ cabbage 8 \/ wheat 4 \/ pumpkin 10 \/ cucumber 7<\/li>\n\n\n\n<li>\u4ef7\u683c 2~4\uff0c\u6062\u590d\u91cf 4~10\uff0c\u4e0e\u4ef7\u683c\u6b63\u76f8\u5173<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u5404\u4fe1\u53f7\u80fd\u91cf\u6d88\u8017\uff08<code>statusinfo.gd:_on_consume_energy*<\/code>\uff09<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u4fe1\u53f7<\/th><th>\u89e6\u53d1\u52a8\u4f5c<\/th><th>\u6263 energy<\/th><th>\u52a0 floor<\/th><\/tr><\/thead><tbody><tr><td><code>hoe_target<\/code><\/td><td>\u9504\u5730 \/ \u6536\u83b7<\/td><td>1<\/td><td>1<\/td><\/tr><tr><td><code>watering_target<\/code><\/td><td>\u6d47\u6c34<\/td><td>1<\/td><td>1<\/td><\/tr><tr><td><code>axe_target<\/code><\/td><td>\u780d\u6811 \/ \u780d\u5efa\u7b51<\/td><td>1<\/td><td>1<\/td><\/tr><tr><td><code>seed_target<\/code><\/td><td>\u64ad\u79cd<\/td><td>0.5<\/td><td>0.5<\/td><\/tr><tr><td><code>building_target<\/code><\/td><td>\u5efa\u9020<\/td><td>0.5<\/td><td>0.5<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">floor \u7d2f\u52a0\u7528 <code>min(energy_max, energy_floor + N)<\/code> \u5c01\u9876\uff0c\u907f\u514d\u5f02\u5e38\u7a81\u7834\u4e0a\u9650\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">2. \u5267\u60c5\u72b6\u6001\u673a\uff1acutscene_trigger \u8fb9\u754c<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><code>game_resource.cutscene_trigger<\/code> \u662f\u6838\u5fc3\u5267\u60c5\u72b6\u6001\uff0c<strong>\u76ee\u524d\u5df2\u77e5\u8fb9\u754c<\/strong>\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>trigger<\/th><th>\u542b\u4e49<\/th><th>\u5f71\u54cd<\/th><\/tr><\/thead><tbody><tr><td>0<\/td><td>\u521d\u59cb\/\u672a\u8fdb\u5165\u5267\u60c5<\/td><td>\u7981\u7528 Shift\uff08\u89c1 \u00a73\uff09<\/td><\/tr><tr><td>1~4<\/td><td>\u5267\u60c5\u5f15\u5bfc\u671f<\/td><td>\u7981\u7528 Shift\u3001\u96e8\u58f0\u64ad\u653e\u3001wuning BGM (Silent Rain Narrative)<\/td><\/tr><tr><td>5<\/td><td>incident \u89c6\u9891\u64ad\u653e<\/td><td>\u89c6\u9891\u4e2d BGM + \u96e8\u58f0\u786c\u505c\uff08<code>pause_bgm_immediately<\/code> \/ <code>pause_rain_immediately<\/code>\uff09<\/td><\/tr><tr><td>6<\/td><td>leave \u5bf9\u8bdd\uff08\u73a9\u5bb6\u5728 wuning \u51fa\u53e3\u9644\u8fd1\uff09<\/td><td>\u770b\u5b8c\u5bf9\u8bdd \u2192 trigger=7<\/td><\/tr><tr><td>7<\/td><td>\u73a9\u5bb6\u51fa\u95e8\u540e<\/td><td>\u8fdb\u5165 SilverMist \u65f6 resume BGM\uff08silver_mist \u81ea\u5df1\u7684\u97f3\u4e50\uff09<\/td><\/tr><tr><td>&gt;7<\/td><td>\u81ea\u7531\u63a2\u7d22<\/td><td>Shift \u542f\u7528\u3001\u6b63\u5e38 BGM<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">\u5404 trigger \u5728\u54ea\u91cc\u88ab\u6539\u5199\uff08owner map\uff09<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u6587\u4ef6<\/th><th>\u6539\u5199<\/th><th>\u65f6\u673a<\/th><\/tr><\/thead><tbody><tr><td><code>wuninghouse_alf.gd:emit_cutscene_trigger()<\/code><\/td><td>\u2192 2<\/td><td><code>cs_pr_pro00_alfroom<\/code> AnimationPlayer call_method track \u8c03<\/td><\/tr><tr><td><code>wuninghouse_cutscene.gd:_on_character_speak01_entered<\/code><\/td><td>2 \u2192 3<\/td><td><code>wuning_house_pro00_02<\/code> \u5bf9\u8bdd\u7ed3\u675f\u540e<\/td><\/tr><tr><td><code>wuninghouse_cutscene.gd:_finalize_video_playback<\/code><\/td><td>3 \u2192 4<\/td><td>incident \u89c6\u9891\u7ed3\u675f\/\u88ab Skip<\/td><\/tr><tr><td><code>wuninghouse_cutscene.gd<\/code><\/td><td>4 \u2192 5<\/td><td><code>wuning_house_pro00_04<\/code>\uff08chest key \u5728 wuning_e \u533a\u57df\uff09+ Sunny \u52a8\u753b + \u53d1\u5e03\u4efb\u52a1 101<\/td><\/tr><tr><td><code>wuninghouse_alf.gd<\/code> <code>_process<\/code><\/td><td>5 \u2192 6<\/td><td>sleep area body_entered + <code>Input.is_action_just_pressed(\"pick\")<\/code> + \u300cSleep\u300d\u52a8\u753b\u64ad\u5b8c + \u65e5\u671f+1\/7:00 + <code>load_level(WuningHouseCorridor)<\/code><\/td><\/tr><tr><td><code>wuninghouse_cutscene.gd<\/code><\/td><td>6 \u2192 7<\/td><td><code>wuning_house_pro00_06<\/code>\uff08leave area\uff09+ <code>pause_bgm_immediately()<\/code><\/td><\/tr><tr><td><code>silver_mist_cutscene.gd:_process<\/code><\/td><td>7 \u2192 8<\/td><td>\u8fdb\u5165 over_area\uff0c\u663e\u793a %Over \u7ed3\u5c40\u9762\u677f<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">WuningHouseAlf sleep area \u6d41\u7a0b\u7ec6\u8282\uff08trigger 5\u21926\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>wuninghouse_alf.gd<\/code> \u6709 <code>var in_sleep_area: bool = false<\/code><\/li>\n\n\n\n<li><code>_on_sleep_area_2d_body_entered<\/code> \u4ec5\u5728 <code>cutscene_trigger == 5<\/code> \u65f6\u8bbe\u4e3a true + <code>%Sleep_f.visible = true<\/code><\/li>\n\n\n\n<li><code>_process<\/code> \u91cc <code>in_sleep_area &amp;&amp; cutscene_trigger == 5 &amp;&amp; Input.is_action_just_pressed(\"pick\")<\/code> \u89e6\u53d1\u6574\u6bb5\uff1a<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><code>character.is_dialogue = true<\/code><\/li>\n\n\n\n<li><code>animation_player.play(\"Sleep\")<\/code> + <code>await animation_finished<\/code><\/li>\n\n\n\n<li><code>cutscene_trigger = 6<\/code><\/li>\n\n\n\n<li>\u65e5\u671f +1\uff08month wrap \/ 12 \u6708 \u2192 Winter \u91cd\u7f6e\uff09<\/li>\n\n\n\n<li><code>hour = 7 \/ minute = 0<\/code><\/li>\n\n\n\n<li><code>load_level(WuningHouseCorridor)<\/code> + \u6062\u590d UI\uff08statusinfo \/ menu \/ time_record\uff09<\/li>\n\n\n\n<li><code>character.is_dialogue = false<\/code><\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">\u26a0\ufe0f <strong>\u6539 trigger \u8fb9\u754c\u524d\u5fc5\u987b\u5148\u67e5\u5b8c\u6574\u5267\u60c5\u6d41\u7a0b<\/strong>\uff0c\u4e0d\u8981\u968f\u4fbf\u6539\u6570\u5b57\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">3. \u89d2\u8272\u8f93\u5165\u9650\u5236<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Sprint\uff08Shift \u5954\u8dd1\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u6587\u4ef6\uff1a<code>compoents\/character\/character.gd:97<\/code><\/li>\n\n\n\n<li>\u5224\u65ad\uff1a<code>is_run = Input.is_action_pressed('run') and CutsceneManager.can_sprint() and _panting_timer &lt;= 0.0<\/code><\/li>\n\n\n\n<li>\u4e1a\u52a1\u89c4\u5219\u96c6\u4e2d\uff1a<code>CutsceneManager.can_sprint()<\/code> \u2192 <code>cutscene_trigger &gt; 6<\/code><\/li>\n\n\n\n<li><strong>\u6539 sprint \u542f\u7528\u6761\u4ef6\u65f6\u4e0d\u8981\u76f4\u63a5\u5728 character.gd \u52a0 if<\/strong>\uff0c\u52a0\u5230 CutsceneManager<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u5598\u6c14\u671f<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u4f53\u529b\u5f52\u96f6 \u2192 <code>_panting_timer = 2.0<\/code>\uff0c\u671f\u95f4 Shift \u65e0\u6548<\/li>\n\n\n\n<li>\u5598\u6c14\u671f\u8fc7\u4e86\u5c31\u5141\u8bb8\u518d\u6309\uff08\u4e0d\u4f1a\u56e0\u4e3a\u4f53\u529b\u4f4e\u5c31\u6b7b\u9501\uff0c\u56e0\u4e3a <code>is_run=true<\/code> \u540e\u4f1a\u7ee7\u7eed\u6263\u4f53\u529b\u518d\u89e6\u53d1\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u8f93\u5165\u52a8\u4f5c\u6e05\u5355\uff08<code>project.godot<\/code> \u7684 <code>[input]<\/code>\uff09<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Action<\/th><th>\u7269\u7406\u952e<\/th><th>\u7528\u9014<\/th><\/tr><\/thead><tbody><tr><td>walk_up\/down\/left\/right<\/td><td>W\/S\/A\/D<\/td><td>\u516b\u5411\u884c\u8d70<\/td><\/tr><tr><td>run<\/td><td>Shift<\/td><td>\u5954\u8dd1<\/td><\/tr><tr><td>bag_switch<\/td><td>Tab\/B<\/td><td>\u5f00\u5173\u80cc\u5305\u9762\u677f\uff08Menu \u4e92\u65a5\uff09<\/td><\/tr><tr><td>select_1..9<\/td><td>\u6570\u5b57\u952e 1-9<\/td><td>\u624b\u6301\u680f\u9009\u683c<\/td><\/tr><tr><td>pick<\/td><td>F<\/td><td>\u62fe\u8d77 \/ \u62fe\u53d6\u5bf9\u8bdd \/ \u7761\u7720\u89e6\u53d1<\/td><\/tr><tr><td>left_mouse<\/td><td>\u9f20\u6807\u5de6\u952e<\/td><td>\u4e3b\u64cd\u4f5c<\/td><\/tr><tr><td>right_mouse<\/td><td>\u9f20\u6807\u53f3\u952e<\/td><td>\u5403\u624b\u6301 Food \u7c7b\u7269\u54c1\uff08<code>consume_food<\/code>\uff09<\/td><\/tr><tr><td>dialogue \/ chest<\/td><td>E<\/td><td>\u63a8\u8fdb\u5bf9\u8bdd \/ \u5f00\u5173\u5b9d\u7bb1<\/td><\/tr><tr><td>task_switch<\/td><td>X<\/td><td>\u5f00\u5173\u4efb\u52a1\u9762\u677f<\/td><\/tr><tr><td>accept<\/td><td>Space<\/td><td>\u63a5\u53d7<\/td><\/tr><tr><td>discard<\/td><td>Q<\/td><td>\u4e22\u5f03<\/td><\/tr><tr><td>page_up \/ page_down<\/td><td>\u9f20\u6807\u4fa7\u952e 4\/5<\/td><td>\u624b\u6301\u680f\u7ffb\u9875\uff08\u5e26 50ms \u51b7\u5374\uff09<\/td><\/tr><tr><td>shift_click_transfer<\/td><td>Shift + \u9f20\u6807\u5de6\u952e<\/td><td>\u80cc\u5305\u2194\u624b\u6301\u2194\u5b9d\u7bb1\u5feb\u901f\u8f6c\u79fb<\/td><\/tr><tr><td>esc<\/td><td>Esc<\/td><td>\u6682\u505c\u83dc\u5355<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">\u9f20\u6807\u7126\u70b9\uff08MouseFocus\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u6bcf\u5e27\u66f4\u65b0\uff1aindoor \/ <code>InterfaceNode.above<\/code> \/ \u5bf9\u8bdd\u4e2d\u65f6\u9690\u85cf\uff1b\u5426\u5219 <code>UtilsManager.transform_position_tile(get_global_mouse_position())<\/code> \u7f51\u683c\u5438\u9644<\/li>\n\n\n\n<li>\u8dd1 + \u70b9\u51fb\u653e\u6811\uff08<code>is_placing_tree<\/code>\uff09\u7684 ImGui \u5165\u53e3\u5df2\u5e9f\u5f03\uff08\u89c1 \u00a712\uff09<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">4. \u97f3\u9891\u7ba1\u7406\u7ea6\u5b9a<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u96e8\u58f0\uff08CutsceneManager\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>_rain_active<\/code> + <code>_manually_paused<\/code> \u4e24\u4e2a\u72b6\u6001\u5b57\u6bb5<\/li>\n\n\n\n<li>\u516c\u5f00\u65b9\u6cd5\uff1a<\/li>\n\n\n\n<li><code>stop_rain()<\/code> \u2014 10 \u79d2\u6e10\u53d8\u505c\uff08\u81ea\u7136\uff09<\/li>\n\n\n\n<li><code>pause_rain_immediately()<\/code> \u2014 \u7acb\u523b\u786c\u505c + \u7f6e <code>_manually_paused=true<\/code>\uff08<strong>\u4e0d<\/strong>\u4f1a\u88ab <code>_process<\/code> \u62c9\u56de\u53bb\u91cd\u542f\uff09<\/li>\n\n\n\n<li><code>resume_rain()<\/code> \u2014 \u590d\u4f4d <code>_manually_paused<\/code> + \u6e10\u5165<\/li>\n\n\n\n<li><code>fade_stop_rain(duration)<\/code> \u2014 \u81ea\u5b9a\u4e49\u65f6\u957f\u6e10\u505c<\/li>\n\n\n\n<li><strong><code>_process<\/code> \u65e9\u8fd4<\/strong>\uff1a<code>if _manually_paused: return<\/code>\uff08line 20-21\uff09\uff0c\u5fc5\u987b\u4fdd\u7559<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">BGM\uff08SoundManager\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u72b6\u6001\u5b57\u6bb5\uff1a<code>_bgm_paused<\/code>\uff08\u624b\u52a8\u6682\u505c\u6807\u5fd7\uff09\u3001<code>_current_level_name<\/code>\uff08\u5f53\u524d\u5173\u5361\u540d\uff09\u3001<code>_bgm_session_id<\/code>\uff08\u81ea\u589e session id\uff09<\/li>\n\n\n\n<li>\u516c\u5f00\u65b9\u6cd5\uff1a<\/li>\n\n\n\n<li><code>pause_bgm_immediately()<\/code> \u2014 \u505c BGM + \u7f6e <code>_bgm_paused=true<\/code> + <strong>\u81ea\u589e <code>_bgm_session_id<\/code><\/strong>\uff08\u8ba9\u65e7\u534f\u7a0b\u9000\u51fa\uff09<\/li>\n\n\n\n<li><code>resume_bgm()<\/code> \u2014 \u590d\u4f4d <code>_bgm_paused<\/code> + \u8c03 <code>play_level_audio_by_name(_current_level_name)<\/code> \u91cd\u65b0\u64ad\u653e<\/li>\n\n\n\n<li><strong><code>play_level_audio_by_name<\/code> \u65e9\u8fd4<\/strong>\uff1a<code>if _bgm_paused: ...<\/code> \u65e9\u8fd4\u524d<strong>\u5fc5\u987b<\/strong>\u8bb0\u5f55 <code>_current_level_name<\/code>\uff0c\u5426\u5219 resume \u4f1a\u64ad\u9519\u5173\u5361<\/li>\n\n\n\n<li>\u7279\u6b8a BGM\uff1a<code>wuninghouse<\/code> \/ <code>wuninghouse_alf<\/code> \/ <code>wuninghouse_corridor<\/code> \u4e09\u4e2a level_name \u8d70 <code>_play_silent_rain_narrative()<\/code>\uff08\u52a0\u8f7d <code>assets\/sound\/bgm\/Silent Rain Narrative.mp3<\/code>\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">BGM \u5206\u53d1\u89c4\u5219\uff08\u6309 level_name\uff09<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>back_level_audio_list<\/code> \u914d\u7f6e\u5728 <code>managers\/sound_manager\/sound_manager.tscn<\/code>\uff0c\u7ed3\u6784\uff1a<code>{ audios: [{audio, volume}, ...], level_name: String }<\/code><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u573a\u666f\u7c7b\u578b<\/th><th>BGM \u6765\u6e90<\/th><\/tr><\/thead><tbody><tr><td><code>birth<\/code><\/td><td>\u5217\u8868\u91cc\u6ce8\u518c\u4e86 <code>birth<\/code>\uff0c\u64ad 4 \u9996\u4e13\u5c5e BGM<\/td><\/tr><tr><td><code>village_01<\/code><\/td><td>\u5217\u8868\u91cc\u6ce8\u518c\u4e86 <code>village_01<\/code>\uff0c\u64ad 2 \u9996\u4e13\u5c5e BGM<\/td><\/tr><tr><td><code>wuninghouse<\/code> \/ <code>wuninghouse_alf<\/code> \/ <code>wuninghouse_corridor<\/code><\/td><td>\u8d70 <code>_play_silent_rain_narrative()<\/code> \u5faa\u73af<\/td><\/tr><tr><td>\u5176\u4ed6\u672a\u6ce8\u518c\u573a\u666f\uff08SilverMist \/ OldPostRd \/ AdventurerGuildRoom_01 \u7b49\uff09<\/td><td><strong>fallback \u5230 <code>_play_mixed_outdoor_audio_loop()<\/code><\/strong>\uff1a\u4ece <code>village_01 + birth<\/code> \u7684 audios \u91cc\u5408\u5e76\u968f\u673a\u9009\u64ad\uff086 \u9996\uff09<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5f53\u524d <code>back_level_audio_list<\/code> \u53ea\u914d\u4e86 <code>birth<\/code> + <code>village_01<\/code> \u4e24\u6761 \u2014 \u5927\u90e8\u5206\u573a\u666f\u8d70 fallback \u6df7\u5408\u6c60<\/li>\n\n\n\n<li>\u65b0\u589e\u573a\u666f\u4e13\u5c5e BGM\uff1a\u5728 <code>.tscn<\/code> \u91cc\u7167 <code>birth<\/code> \u90a3\u6761\u683c\u5f0f\u52a0\u4e00\u884c <code>level_name: \"&lt;\u573a\u666f\u540d&gt;\"<\/code> + audios \u6570\u7ec4\u5373\u53ef\uff0c\u65e0\u9700\u6539 .gd<\/li>\n\n\n\n<li>\u6838\u5fc3\u5faa\u73af\u5df2\u62bd\u5230 <code>_play_audio_pool_loop(audio_pool: Array, session_id)<\/code>\uff0c<code>play_level_audio_loop<\/code> \/ <code>_play_mixed_outdoor_audio_loop<\/code> \u90fd\u59d4\u6258\u7ed9\u5b83<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">BGM \u534f\u7a0b\u751f\u547d\u5468\u671f\uff08session id \u9632 race condition\uff0c2026-06\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>bug \u573a\u666f<\/strong>\uff1a\u65e7\u8bbe\u8ba1\u7528 <code>is_back_audio_running<\/code> \u5168\u5c40\u6807\u5fd7 + <code>pending_level_name<\/code> \u63a5\u529b\u673a\u5236\u3002\u534f\u7a0b\u5728 <code>await timer<\/code>\uff0810-30 \u79d2\uff09\u671f\u95f4\uff0c\u65b0\u534f\u7a0b\u542f\u52a8 \u2192 <code>is_back_audio_running<\/code> \u88ab\u65b0\u534f\u7a0b\u91cd\u8bbe True \u2192 \u65e7\u534f\u7a0b\u9192\u6765\u4e0d\u9000\u51fa \u2192 <strong>\u4e24\u4e2a\u534f\u7a0b\u62a2\u540c\u4e00\u4e2a <code>back_audio_player<\/code><\/strong> \u2192 BGM \u4e00\u9996\u6ca1\u64ad\u5b8c\u5c31\u505c\u6216\u8be1\u5f02\u5207\u6362<\/li>\n\n\n\n<li><strong>fix<\/strong>\uff1a\u6bcf\u6b21 <code>play_level_audio_by_name<\/code> \/ <code>pause_bgm_immediately<\/code> \/ <code>stop_level_audio<\/code> \u81ea\u589e <code>_bgm_session_id<\/code>\u3002\u534f\u7a0b\u542f\u52a8\u65f6\u8bb0\u5f55 <code>my_session = _bgm_session_id<\/code>\uff0c\u6bcf\u6b21 await \u540e\u68c0\u67e5 <code>_bgm_session_id != session_id<\/code> \u5219 return \u9000\u51fa<\/li>\n\n\n\n<li><strong><code>AudioStreamPlayer.stop()<\/code> \u4e0d emit <code>finished<\/code><\/strong>\uff08Godot 4 \u5df2\u77e5\u884c\u4e3a\uff09\uff0c\u6240\u4ee5 <code>pause_bgm_immediately<\/code> \u5fc5\u987b\u81ea\u589e session id\u2014\u2014\u5426\u5219\u534f\u7a0b\u5361\u5728 <code>await back_audio_player.finished<\/code> \u6c38\u8fdc\u4e0d\u4f1a\u88ab\u5524\u9192\uff0c\u4e0b\u6b21\u522b\u7684\u534f\u7a0b\u8ba9 player emit finished \u65f6\u65e7\u534f\u7a0b\u4e5f\u9192\u6765 \u2192 race condition<\/li>\n\n\n\n<li><strong><code>pending_level_name<\/code> \u5b57\u6bb5\u5df2\u5220\u9664<\/strong>\uff1a\u539f\u672c&#8221;\u7b49\u5f53\u524d\u9996\u64ad\u5b8c\u518d\u5207\u6362&#8221;\u7684\u8bbe\u8ba1\u5df2\u88ab session id \u673a\u5236\u53d6\u4ee3\u2014\u2014\u5207\u5173\u76f4\u63a5\u8d70\uff0c\u65b0\u534f\u7a0b\u7684\u6de1\u5165\u6de1\u51fa\u4f1a\u5904\u7406\u5207\u6362\u5e73\u6ed1\u5ea6<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u89e6\u53d1\u70b9\uff08game.gd <code>load_level<\/code> \u5f02\u6b65\u52a0\u8f7d\u5b8c\u6210\u65f6\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>level_loaded.emit()<\/code> \u4e4b\u540e\u6309 LevelType \u5206\u53d1\uff1a<\/li>\n\n\n\n<li><code>LevelType.Birth<\/code> \u2192 <code>task.try_complete_by_signal(&amp;\"Reach_Birth\")<\/code><\/li>\n\n\n\n<li><code>LevelType.SilverMist &amp;&amp; cutscene_trigger == 7<\/code> \u2192 <code>SoundManager.resume_bgm()<\/code><\/li>\n\n\n\n<li><code>LevelType.WuningHouseAlf &amp;&amp; cutscene_trigger == 1<\/code> \u2192 \u64ad <code>cs_pr_pro00_alfroom<\/code> \u5f00\u573a\u8fc7\u573a<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u968f\u673a\u97f3\u6548\u6c60<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u52a8\u4f5c<\/th><th>\u97f3\u6548<\/th><\/tr><\/thead><tbody><tr><td>\u9504\u5730<\/td><td><code>hoe_01<\/code> ~ <code>hoe_03<\/code>\uff083 \u6863\u968f\u673a\uff09<\/td><\/tr><tr><td>\u6d47\u6c34<\/td><td><code>watering_01<\/code> ~ <code>watering_04<\/code>\uff084 \u6863\u968f\u673a\uff09<\/td><\/tr><tr><td>\u780d\u6811<\/td><td><code>axe_01<\/code> ~ <code>axe_04<\/code>\uff084 \u6863\u968f\u673a\uff09+ camera.shake<\/td><\/tr><tr><td>\u8d70\u8def\uff08\u8349\u5730\uff09<\/td><td><code>walk_at_grass_01<\/code> ~ <code>walk_at_grass_07<\/code>\uff087 \u6863\u968f\u673a\uff0cvolume -16\uff09<\/td><\/tr><tr><td>\u8d70\u8def\uff08\u77f3\u5934\/\u8def\uff09<\/td><td><code>walk_at_stone_01<\/code> ~ <code>walk_at_stone_05<\/code>\uff085 \u6863\u968f\u673a\uff0cvolume -10\uff09<\/td><\/tr><tr><td>\u5b9d\u7bb1\u5f00<\/td><td><code>chest_open_01<\/code> ~ <code>chest_open_03<\/code>\uff083 \u6863\u968f\u673a\uff09<\/td><\/tr><tr><td>\u5b9d\u7bb1\u5173<\/td><td><code>chest_close_01<\/code> ~ <code>chest_close_03<\/code>\uff083 \u6863\u968f\u673a\uff09<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">5. \u4efb\u52a1\u7cfb\u7edf\u6269\u5c55<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u573a\u666f\u89e6\u53d1\u5b8c\u6210\u4efb\u52a1<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>TaskResource.done_signal: StringName<\/code> \u2014 \u4efb\u52a1\u81ea\u5df1\u586b\u4fe1\u53f7\u540d\uff08\u5982 <code>&amp;\"Reach_Birth\"<\/code>\uff09<\/li>\n\n\n\n<li><code>TaskResource.complete()<\/code> \u2014 \u5916\u90e8\u8c03\uff0c\u628a\u4efb\u52a1\u6807 done + emit <code>done_triggered<\/code><\/li>\n\n\n\n<li><code>Task.try_complete_by_signal(sig_name)<\/code> \u2014 \u904d\u5386\u4efb\u52a1\u5217\u8868\u627e\u5339\u914d\u7684\uff0c<strong>\u6807\u5b8c\u6210 + \u81ea\u52a8 over\uff08\u8c03 <code>to_over_task<\/code>\uff1a\u53d1\u5956\u52b1 + \u79fb\u5230 over_list\uff09<\/strong>\u3002\u8bbe\u8ba1\u610f\u56fe\uff1adone_signal \u89e6\u53d1\u7684\u4efb\u52a1\u6ca1\u6709 NPC \u4ea4\u63a5\u73af\u8282\uff0c\u573a\u666f\u5230\u8fbe = \u5b8c\u6210 + \u7acb\u5373\u53d1\u5956\u52b1\u3002\u4e0d\u8981\u624b\u52a8\u518d\u8c03\u4e00\u6b21 <code>to_over_task<\/code>\u3002<\/li>\n\n\n\n<li><strong>\u65b0\u589e\u300c\u573a\u666f\u5230\u8fbe\u5b8c\u6210\u4efb\u52a1\u300d\u7684\u6807\u51c6\u505a\u6cd5<\/strong>\uff1a<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u5728 <code>game.gd<\/code> <code>level_loaded.emit()<\/code> \u4e4b\u540e\u52a0 <code>if level == X: task.try_complete_by_signal(&amp;\"Y\")<\/code><\/li>\n\n\n\n<li>\u5728\u5bf9\u5e94 <code>TaskResource.tres<\/code> \u52a0 <code>done_signal = &amp;\"Y\"<\/code><\/li>\n\n\n\n<li>\u4e0d\u8981\u5199\u5728 <code>_process<\/code> \u91cc\uff08\u6bcf\u5e27\u89e6\u53d1\u4f1a\u51fa\u95ee\u9898\uff09<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u5982\u679c\u672a\u6765\u9700\u8981\u300c\u573a\u666f\u5230\u8fbe\u6807\u5b8c\u6210\uff0c\u4f46\u5956\u52b1\u7531 NPC \u540e\u7eed\u4ea4\u63a5\u624d\u53d1\u300d<\/strong>\uff1a\u90a3\u662f\u53e6\u4e00\u79cd\u4efb\u52a1\u6a21\u578b\uff0c\u4e0d\u8981\u8d70 <code>done_signal<\/code>\uff0c\u5e94\u8be5\u7528 <code>CollectTaskDetailResource<\/code> + NPC dialogic signal <code>over_task<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Task UI \u7684\u4e24\u4e2a signal<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Task.detail_closed<\/code> \u2014 Detail \u9762\u677f\uff08\u53f3\u4fa7\u8be6\u60c5\uff09\u5173\u95ed<\/li>\n\n\n\n<li><code>Task.task_closed<\/code> \u2014 <strong>\u6574\u4e2a Task \u4e3b\u9762\u677f<\/strong>\u5173\u95ed\uff08\u5305\u62ec Detail + \u5217\u8868\uff09<\/li>\n\n\n\n<li>\u5267\u60c5\u811a\u672c\u91cc\u8981\u300c\u5c55\u793a\u4efb\u52a1\u7ed9\u73a9\u5bb6\u770b\u300d\u5c31 <code>await task.task_closed<\/code>\uff08<strong>\u4e0d\u8981<\/strong> await <code>detail_closed<\/code>\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u89e6\u53d1\u987a\u5e8f\u5751<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Task.menu.on_click_item(\"Task\")<\/code> \u8c03 <code>switch()<\/code> \u662f\u5e26 0.15s \u52a8\u753b\u7684\uff0c\u4e0d\u4f1a await<\/li>\n\n\n\n<li>\u7d27\u63a5\u7740\u8c03 <code>on_click_task_item<\/code> \u9009\u4efb\u52a1\u65f6\uff0c<strong>\u4e3b\u9762\u677f\u8fd8\u6ca1\u5b8c\u5168\u663e\u793a<\/strong>\uff0c\u8981\u52a0 <code>await get_tree().create_timer(0.5).timeout<\/code> \u515c\u5e95<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">TaskState enum<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>enum TaskState { Un_Get, Un_Done, Done, Finish }<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Un_Get<\/code>\uff1a\u672a\u63a5\u53d6\uff08<code>get_task_from_id<\/code> \u8fd4\u56de null\uff09<\/li>\n\n\n\n<li><code>Un_Done<\/code>\uff1a\u5df2\u63a5\u53d6\uff0c\u672a\u5b8c\u6210\uff08<code>task.done == false<\/code>\uff09<\/li>\n\n\n\n<li><code>Done<\/code>\uff1a\u5b8c\u6210\u672a\u4ea4\u63a5\uff08<code>task.done == true<\/code>\uff09<\/li>\n\n\n\n<li><code>Finish<\/code>\uff1a\u5b8c\u6210\u5e76\u4ea4\u63a5\uff08<code>over_list<\/code> \u91cc\u6709 id\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u4efb\u52a1\u5237\u65b0\u89e6\u53d1\u70b9<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>attribute.task.refresh_task_state(npc)<\/code> \u5728\u5bf9\u8bdd\u5f00\u59cb\/\u7ed3\u675f\u65f6\u8c03\uff08<code>character.gd:on_dialogue_timeline_started\/ended<\/code>\uff09\uff0c\u91cd\u65b0\u68c0\u6d4b <code>CollectTaskDetailResource<\/code> \u7684 <code>has\/count<\/code><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">6. \u9879\u76ee\u7ed3\u6784\u6027\u5751\uff08\u5df2\u8e29\u8fc7\u7684\uff09<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u901a\u7528<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>_process<\/code> \u91cc\u653e\u300c\u6301\u7eed\u6761\u4ef6\u89e6\u53d1\u7684\u5bf9\u8bdd\u300d\u662f\u53cd\u6a21\u5f0f \u2192 \u73a9\u5bb6\u5728\u533a\u57df\u91cc\u4e00\u5e27\u89e6\u53d1\u4e00\u6b21\uff08\u524d\u9762 leave \u5bf9\u8bdd\u8e29\u8fc7\uff09\u3002\u4fe1\u53f7\u56de\u8c03\uff08<code>_on_*_body_entered<\/code>\uff09\u624d\u662f\u300c\u8fb9\u6cbf\u89e6\u53d1\u300d\u7684\u6b63\u786e\u5199\u6cd5<\/li>\n\n\n\n<li><code>.tres<\/code> \u91cc StringName \u5b57\u6bb5\u7684\u6807\u51c6\u5199\u6cd5\uff1a<code>done_signal = &amp;\"Name\"<\/code><\/li>\n\n\n\n<li>Godot 4 \u7528 UID \u8ddf\u8e2a\u8d44\u6e90\uff0c<strong>\u91cd\u547d\u540d\u8d44\u6e90\u6587\u4ef6 UID \u4e0d\u53d8<\/strong>\uff0c\u5f15\u7528\u65b9\u96f6\u6539\u52a8<\/li>\n\n\n\n<li>\u627e\u8d44\u6e90\u5f15\u7528\u65f6\u5fc5\u987b\u8986\u76d6 3 \u79cd\u5f62\u5f0f\uff1a\u6587\u4ef6\u8def\u5f84\u3001UID\u3001\u5b57\u7b26\u4e32\/\u53c2\u6570\u91cc\u7684 ID\uff08DTL \u5bf9\u8bdd\u6587\u4ef6\u4e5f\u5f97\u641c\uff09<\/li>\n\n\n\n<li><code>CanvasLayer<\/code> \u7236\u8282\u70b9 modulate \u4e0d\u5f71\u54cd\u5b50\u8282\u70b9<\/li>\n\n\n\n<li><code>Task.to_add_task(id)<\/code> <strong>\u4e0d\u53bb\u91cd<\/strong>\uff08<code>task.gd:201-204<\/code> \u76f4\u63a5 <code>push_back<\/code>\uff09\uff0c\u91cd\u590d add \u4f1a\u8ba9\u4efb\u52a1\u5217\u8868\u91cc\u51fa\u73b0\u4e24\u4e2a\u4e00\u6837\u7684\u4efb\u52a1\u3002\u6d89\u53ca\u300c\u53d1\u5b8c\u5956\u518d\u542f\u52a8 tips\u300d\u8fd9\u79cd\u4e8c\u6b21\u89e6\u53d1\u7684\u5267\u60c5\u811a\u672c\uff0c\u5fc5\u987b\u7528 <code>if not get_task_from_id(id): to_add_task(id)<\/code> \u5b88\u536b<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">NPC<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u65b0\u5efa\/\u590d\u5236 NPC \u5b50\u573a\u666f\u5fc5\u987b\u663e\u5f0f\u7ed1 <code>interact = NodePath(\"Interact\")<\/code><\/strong>\uff1a\u57fa\u7c7b <code>compoents\/npc\/npc.tscn<\/code> \u628a <code>interact: Control<\/code> \u58f0\u660e\u4e3a <code>@export<\/code>\uff0c\u5b50\u573a\u666f\uff08<code>npc&lt;id&gt;.tscn<\/code>\uff09\u7684\u6839\u8282\u70b9\u5fc5\u987b\u5e26 <code>node_paths=PackedStringArray(\"interact\")<\/code> + <code>interact = NodePath(\"Interact\")<\/code> \u8d4b\u503c\u3002\u6f0f\u4e86\u4e4b\u540e BT \u9996\u5e27\u8dd1\u300c\u4e0d\u5728\u8303\u56f4\u5185\u300d\u5e8f\u5217 \u2192 <code>ai\/tasks\/set_interace_visible.gd:6<\/code> \u6267\u884c <code>npc.interact.visible = visible<\/code> \u2192 <code>interact<\/code> \u662f null \u2192 \u629b &#8220;Invalid get\/set on a null instance&#8221;\uff0c\u8868\u73b0\u662f\u300c\u4e00\u8fdb level \u7acb\u523b\u5d29\u300d\u3002<strong><code>schedule_list_resource<\/code> \u662f\u53ef\u9009\u7684<\/strong>\uff08<code>npc.gd:39<\/code> \u6709 <code>if !schedule_list_resource: return<\/code> \u5b88\u536b\uff0cNPC \u7ad9\u6869\u4e0d\u79fb\u52a8\u65f6\u4e0d\u6302\u4e5f\u4e0d\u4f1a\u5d29\uff09\u3002\u590d\u5236 NPC \u65f6\u68c0\u67e5 4 \u4ef6\u5957\uff1ascene \u6839\u8282\u70b9 <code>interact<\/code> \u7ed1\u4e86\u3001BT \u7684 <code>dialogue_name<\/code> \u6307\u5411\u81ea\u5df1\u7684 dtl\u3001dtl \u91cc <code>[style]<\/code> \u548c <code>npc&lt;id&gt;_speaker:<\/code> \u90fd\u6362\u6210\u65b0 NPC\u3001<code>npc.name<\/code> \u5728 silver_mist \u5b9e\u4f8b\u5316\u65f6\u5982\u975e <code>npc&lt;id&gt;<\/code> \u4e0d\u5f71\u54cd\uff08speaker style \u4e0d\u6309 name \u6ce8\u518c character\uff0c\u53ea\u6709 bubble style \u7528 <code>npc.name.to_lower()<\/code> \u62fc dch\uff09<\/li>\n\n\n\n<li><strong><code>NPC.NPC_TYPE<\/code> \u5b57\u5178\u5fc5\u987b\u542b\u6bcf\u4e2a <code>NpcType<\/code> \u503c<\/strong>\uff1a<code>character.gd:to_shop<\/code> \u8d70 <code>NPC.NPC_TYPE.get(npc)<\/code>\uff0c\u7f3a\u5931\u4f1a push_error\u3002\u52a0\u65b0 NpcType \u65f6\u52a1\u5fc5\u540c\u6b65\u52a0\u6620\u5c04<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Input \/ \u5f02\u6b65<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>Input.is_action_just_pressed<\/code> \u8fb9\u6cbf\u4f1a\u88ab\u300c\u52a8\u753b finished \u56de\u8c03\u91cc\u7684 await\u300d\u63a5\u4f4f\u8bef\u89e6\u53d1<\/strong>\u3002\u4f8b\u5982 page_gift \u5173\u95ed\u6d41\u7a0b\uff1a\u73a9\u5bb6\u70b9 left_mouse \u5173\u95ed \u2192 tween 150ms \u2192 finished \u56de\u8c03\u91cc await \u76d1\u542c\u8f93\u5165 \u2192 <strong>\u521a\u624d\u90a3\u6b21\u7684 left_mouse.just_pressed \u72b6\u6001\u8fd8\u6ca1\u88ab\u6d88\u8d39<\/strong>\uff08_process \u5df2\u8dd1\u8fc7\u90a3\u4e00\u5e27\uff09\uff0cawait \u7b2c\u4e00\u5e27\u5c31\u547d\u4e2d \u2192 \u7acb\u523b\u5173\u6389\u540e\u7eed tips\u3002<strong>\u4fee\u6cd5<\/strong>\uff1a\u5728\u65b0\u7684 await \u5faa\u73af\u524d <code>await get_tree().process_frame<\/code> \u7b49\u4e00\u5e27\uff0c\u8ba9\u90a3\u4e00\u5e27\u7684 just_pressed \u8fb9\u6cbf\u5728 _process \u9636\u6bb5\u88ab\u6d88\u8d39\u6389<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Inventory<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>InventoryNode.holding_item<\/code> \u662f static dict<\/strong>\uff1a\u8de8\u6240\u6709 bag\/hold\/chest \u69fd\u5171\u4eab\u5f53\u524d\u624b\u6301\u7269\u54c1\uff1b<code>MAX_STACK_SIZE = 64<\/code>\uff0chalf-split \u662f\u53f3\u51fb\u4e00\u534a\uff1b<code>DOUBLE_CLICK_INTERVAL = 0.3s<\/code><\/li>\n\n\n\n<li>\u80cc\u5305\u5de5\u5177\u63d0\u793a\u5ef6\u8fdf 1.2s\uff1a\u592a\u5feb\u5212\u8fc7\u4e0d\u95ea\u9762\u677f\uff0c\u4f46\u7528\u4e86 <code>cancel timer<\/code> \u9632 race<\/li>\n\n\n\n<li><strong>\u5408\u5e76\u89c4\u5219<\/strong>\uff1amerge same-id stacks \u2192 drop \u5230\u9996\u4e2a\u7a7a\u69fd \u2192 \u5426\u5219 swap \u56de <code>holding_item<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Typo\uff08\u4fdd\u7559\u4ee5\u517c\u5bb9\u65e7\u4ee3\u7801\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>BuildingResource<\/code> \u62fc\u5199\u662f colums<\/strong>\uff08\u4e0d\u662f columns\uff09\uff0cChestResource \u4e5f\u662f <code>colums: int<\/code><\/li>\n\n\n\n<li><strong><code>SeedResource.groth_time_state<\/code><\/strong> \u62fc\u5199\u662f <code>groth<\/code>\uff08\u4e0d\u662f growth\uff09\uff0c\u6570\u7ec4\u957f\u5ea6 = \u5e27\u6570 &#8211; 1<\/li>\n\n\n\n<li><strong><code>Level.TileMapLayerContianer<\/code><\/strong> \u62fc\u5199\u662f <code>Contianer<\/code>\uff08\u4e0d\u662f Container\uff09\uff0c<code>Level.set_character_postion<\/code> \u4e5f\u662f typo\uff08\u4e0d\u662f position\uff09<\/li>\n\n\n\n<li><strong><code>Level.load_soild_cell()<\/code><\/strong> \u62fc\u5199\u662f <code>soild<\/code>\uff08\u4e0d\u662f solid\uff09<\/li>\n\n\n\n<li><strong><code>FellableBase.highlight_are<\/code><\/strong> \u62fc\u5199\u662f <code>are<\/code>\uff08\u4e0d\u662f area\uff09<\/li>\n\n\n\n<li><strong><code>Chest.animtion_player<\/code><\/strong> \u62fc\u5199\u662f <code>animtion<\/code>\uff08\u4e0d\u662f animation\uff09<\/li>\n\n\n\n<li><strong><code>Chest.ToOpen \/ ToClose<\/code><\/strong> \u5927\u5c0f\u5199\u4e0d\u89c4\u8303\uff08\u4e0d\u662f to_open\uff09<\/li>\n\n\n\n<li><strong><code>ai\/tasks\/set_interace_visible.gd<\/code><\/strong> \u62fc\u5199\u662f <code>interace<\/code>\uff08\u4e0d\u662f interface\uff09<\/li>\n\n\n\n<li><strong><code>wuninghouse_corridor_wuningromm.gd<\/code><\/strong> \u6587\u4ef6\u540d\u62fc\u5199\u662f <code>wuningromm<\/code>\uff08\u4e0d\u662f wuningroom\uff09<\/li>\n\n\n\n<li><strong><code>get_astar_path_to(start, end, callback)<\/code><\/strong> \u7684 <code>callback<\/code> \u53c2\u6570\u5f53\u524d\u662f dead code\uff0c\u51fd\u6570\u4f53\u6ca1\u7528<\/li>\n\n\n\n<li><strong>FellableBase \u7684 occluder \u5b57\u6bb5\u540d<\/strong>\uff1a<code>occluder_normal<\/code> \/ <code>occluder_stump<\/code> \/ <code>occluder_seasonal<\/code>\uff0c\u5b63\u8282\u8d34\u56fe\u5b57\u6bb5\u662f <code>collapse_altas_*<\/code>\uff08typo\uff1aaltas \u4e0d\u662f atlas\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Inventory \/ Building<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Building \u653e\u7f6e\u7684 terrain id \u5fc5\u987b\u5728 <code>Inventory.terrain_id<\/code> \u91cc\u624b\u52a8\u58f0\u660e\uff0c\u4e0d\u8981\u9760 <code>id - 8001<\/code> \u7b97<\/strong>\uff08<code>levels\/level.gd:485-489<\/code>\uff09\u3002TileSet <code>terrain_set_0<\/code> \u987a\u5e8f\u662f\u7f8e\u672f\u6309\u5bb6\u5177\u5206\u7c7b\u786c\u6392\u7684\uff08fence\/chest\/bed\/bonsai\/book \u5728 0~8\uff0cbook03\/bowl\/candle\/chair\/foods\/paintings\/plates\/sofa\/toilet\/tv \u6bb5\u662f\u53e6\u8d77 id\uff09\uff0c\u8ddf inventory id \u5b8c\u5168\u8131\u94a9\u3002\u5982\u679c\u7528 <code>id - 8001<\/code> \u7b97\uff1afence\/chest\/bed \u51d1\u5de7\u5bf9\u4e0a\uff080~2\uff09\uff0c\u4f46 <code>paintings07<\/code> (id 8066) \u4f1a\u7b97\u6210 65 \u2192 \u547d\u4e2d <code>paintings10<\/code> \u7684\u56fe\uff1b<code>paintings10<\/code> (id 8069) \u2192 68 \u2192 <code>plates01<\/code>\u3002\u6bcf\u4e2a building .tres \u81ea\u5df1\u58f0\u660e <code>terrain_id = N<\/code>\uff08\u5bf9\u5e94 <code>used\/tileset\/building\/building.tres<\/code> \u7684 <code>terrain_set_0\/terrain_N<\/code>\uff09\uff0c\u65b0\u589e building \u65f6\u5fc5\u987b\u67e5 TileSet \u62ff\u6b63\u786e\u7684 terrain id \u586b\u8fdb\u53bb\uff0c\u4e0d\u80fd\u590d\u5236 <code>id - 8001<\/code><\/li>\n\n\n\n<li><strong><code>Inventory.terrain_id<\/code> \u7f3a\u7701\u503c\u662f -1<\/strong>\uff0c\u53ea\u6709 <code>add_building<\/code> \u624d\u4f1a\u7528\uff08\u4e14\u53ea\u5728 <code>&lt; 0<\/code> \u65f6\u624d\u515c\u5e95\u56de <code>id - 8001<\/code>\uff09\uff0c\u5176\u4ed6 InventoryType\uff08weapon\/material\/seed\/food\/tool\/crop\uff09\u4e0d\u9700\u8981\u586b\u3002Inventory \u5b57\u6bb5\u987a\u5e8f\uff1a<code>structs\/inventory.gd<\/code> \u91cc\u65b0\u5b57\u6bb5\u52a0\u5728\u6700\u540e<\/li>\n\n\n\n<li><strong><code>Inventory.restore_value<\/code> \u7f3a\u7701\u503c\u662f 0<\/strong>\uff1a\u53ea Food\/Medicine \u751f\u6548\uff0c\u5176\u4ed6\u7c7b\u578b\u4fdd\u6301 0\uff1b\u8d70 floor -= N \u6a21\u578b\uff08\u8be6\u89c1 \u00a71\uff09<\/li>\n\n\n\n<li><strong>BuildingResource.BuildingType enum \u5df2\u5e9f\u5f03<\/strong>\uff08Fence\/Chest\/Bed \u4e09\u9879\uff09\uff0c<code>add_building<\/code> \u5b9e\u9645\u6309 <code>terrain_id<\/code> \u7d22\u5f15\u800c\u975e enum \u5f15\u7528\u3002<strong>\u65b0\u4ee3\u7801\u4e0d\u5199\u8fd9\u4e2a enum<\/strong>\u2014\u2014\u4fdd\u7559\u4ec5\u4e3a\u65e7\u903b\u8f91\u517c\u5bb9<\/li>\n\n\n\n<li><strong>silver_mist \u573a\u666f\u6709 Building TileMapLayer<\/strong>\uff08<code>silver_mist.tscn:112 [node name=\"Building\" parent=\"TileMapLayerContianer\" index=\"7\"]<\/code>\uff09\u3002<code>Level.building_layer<\/code> \u4e0d\u4e3a null\uff0c\u53ef\u4ee5\u6b63\u5e38 add_building \/ \u780d\u5efa\u7b51<\/li>\n\n\n\n<li><strong>\u53ef\u7834\u574f\u5efa\u7b51\u8d70 Breakable \u901a\u7528\u5165\u53e3<\/strong>\uff082026-06 \u91cd\u6784\uff09\uff1a\u65a7\u5b50 \/ \u672a\u6765\u5176\u4ed6\u5de5\u5177\u90fd\u8d70 <code>Breakable.hit(tool, at)<\/code>\uff0c<strong>\u4e0d\u8981\u5728 <code>Level<\/code> \u4e0a\u52a0\u65b0\u7684\u7279\u4f8b\u65b9\u6cd5<\/strong>\u3002\u6bcf\u4e2a level \u5b9e\u4f8b\u7ef4\u62a4 <code>var breakables: Array[Breakable]<\/code>\uff1b<code>add_building<\/code> \u65f6\u6302 Breakable\uff0c<code>load_buildings<\/code> \u65f6\u6309 <code>cell_to_inventory_id<\/code> \u91cd\u5efa\u3002\u914d\u7f6e\u8868\u96c6\u4e2d\u5728 <code>Level<\/code> \u9876\u90e8\u4e24\u4e2a const\uff08<code>BREAKABLE_SCRIPT_BY_INVENTORY_ID<\/code> \/ <code>BREAKABLE_HITS_NEEDED_BY_INVENTORY_ID<\/code>\uff09\u2014\u2014\u52a0\u65b0\u7279\u4f8b\u6539\u8fd9\u4e24\u5f20\u8868\uff0c\u4e0d\u52a8 inventory \u8d44\u6e90\u3002fence_axe_count \u5b57\u6bb5\u5df2\u5e9f\u5f03\uff0c\u65b0\u4ee3\u7801\u4e0d\u5199\uff08\u4fdd\u7559\u4ec5\u4e3a\u65e7 .tres \u517c\u5bb9\uff09<\/li>\n\n\n\n<li><strong>\u52a0\u65b0 building \u7269\u54c1\u52a1\u5fc5\u540c\u6b65\u767b\u8bb0 <code>_INVENTORY_ID_TO_FILENAME<\/code><\/strong>\uff08<code>levels\/level.gd<\/code>\uff09\uff1a\u8fd9\u662f <code>load_buildings<\/code> \u5b58\u6863\u91cd\u5efa Breakable \u7684 <code>cell_to_inventory_id \u2192 .tres \u6587\u4ef6\u540d<\/code> \u53cd\u67e5\u8868\u3002\u6f0f\u767b\u8bb0\u65f6 <code>load_buildings<\/code> \u4f1a <code>push_warning<\/code> + skip \u8be5 cell\u2014\u2014\u540e\u679c\u662f<strong>\u65b0\u653e\u80fd\u780d\u3001\u5b58\u6863\u91cd\u8f7d\u540e\u5c31\u780d\u4e0d\u52a8\u4e86<\/strong>\uff08\u56e0\u4e3a\u6ca1\u6302 Breakable \u5b50\u8282\u70b9\uff0c<code>get_breakable_at<\/code> \u627e\u4e0d\u5230\uff09\u3002\u65b0 building .tres \u52a0\u5b8c\u540e\u52a1\u5fc5\u540c\u6b65\u52a0\u4e00\u884c\uff08\u76ee\u524d\u5b9e\u9645 <strong>92 \u9879<\/strong>\uff0c\u7f3a\u53f7 8061\/8062\/8063\uff1b\u540e\u7eed\u6309\u9700\u8865\u3002\u8fd9\u662f\u8bbe\u8ba1\u4e0a\u7684 hard-coded \u6620\u5c04\u2014\u2014\u76ee\u524d\u6ca1\u6709\u81ea\u52a8\u626b\u76ee\u5f55\u673a\u5236\uff09<\/li>\n\n\n\n<li><strong><code>tellable<\/code> \u53ef\u7834\u574f\u88c5\u9970 tile<\/strong>\uff082026-06 \u65b0\u589e\uff0c2026-06 \u6539\u4e3a\u6301\u4e45\u5316\uff09\uff1a\u573a\u666f\u4e2d TileMapLayer \u52a0 <code>metadata\/tellable = true<\/code>\uff08\u5982 Afforest \u5c42\uff09\uff0cLevel._ready \u626b\u63cf\u8be5\u5c42\u6240\u6709 tile \u6302 <code>BreakableTellable<\/code>\uff0c\u9504\u5934 1 \u4e0b\u64e6 tile\u3002<strong>\u5df2\u5b58\u6863<\/strong>\uff08<code>BuildingResource.tellable_broken_cells<\/code> \u6309 layer_key \u5206\u7ec4\u5b58\u88ab\u64e6 cell\uff09\u2014\u2014reload \u65f6\u6309\u5b58\u6863\u5217\u8868\u53cd\u5411 erase_cell \u8fd8\u539f\u64e6\u6389\u72b6\u6001\u3002<strong>\u53ea\u8d70 Breakable.hit() \u901a\u7528\u5165\u53e3<\/strong>\uff0c\u4f46\u53ea\u6709\u9504\u5934\uff08<code>_tool == &amp;\"hoe\"<\/code>\uff09\u80fd\u547d\u4e2d\u2014\u2014<code>BreakableTellable.hit()<\/code> \u81ea\u8eab\u505a\u5de5\u5177\u5b88\u536b\uff0c\u65a7\u5934\u8d70 <code>_tool != &amp;\"hoe\"<\/code> silent skip<\/li>\n\n\n\n<li><strong>\u7f8e\u672f\u8f85\u52a9\u5c42\u7ea6\u5b9a\uff08visible=false \u7684 TileMapLayer\uff09<\/strong>\uff082026-06 \u4fee\u780d\u5b8c\u6811\u540e\u4e0d\u80fd\u8015\u5730 bug\uff09\uff1asilver_mist \/ birth \/ village_01 \/ old_post_rd \u56db\u4e2a outdoor \u573a\u666f\u90fd\u6709\u4e00\u4e2a Tree2\uff08\u6216 Tree\uff09TileMapLayer \u5f53\u5173\u5361\u8bbe\u8ba1\u7684\u5b9a\u4f4d\u53c2\u8003\u5c42\uff0c<strong>\u8fd0\u884c\u65f6 <code>visible = false<\/code> \u4e0d\u6e32\u67d3<\/strong>\u3002\u4f46 tile \u6570\u636e\u4ecd\u5728 \u2014\u2014 \u4e4b\u524d\u4f1a\u963b\u6321\u9504\u5730\u5224\u5b9a\uff08<code>get_current_tile_can_hoe<\/code> \u81ea\u9876\u5411\u4e0b\u904d\u5386\u65f6\u5148\u547d\u4e2d\u9876\u5c42 tree tile \u2192 \u975e farmland \u2192 return false\uff1b\u8868\u73b0\u662f\u300c\u780d\u5b8c\u6811\u540e\u90a3\u5757\u5730\u4e0d\u80fd\u8015\u5730\u300d\uff09\u3002\u4fee\u590d\u5728 <code>levels\/level.gd:_get_topdown_layers()<\/code>\uff1a\u904d\u5386\u65f6 <code>if not c.visible: continue<\/code>\uff0c\u6240\u6709\u8d70\u8fd9\u51fd\u6570\u7684\u67e5\u8be2\uff08\u9504\u5730\u5224\u5b9a\u3001terrain_type \u7b49\uff09\u90fd\u81ea\u52a8\u8df3\u8fc7\u7f8e\u672f\u8f85\u52a9\u5c42\u3002<strong>\u65b0\u589e TileMapLayer \u65f6\u52a1\u5fc5\u9075\u5b88<\/strong>\uff1a\u662f\u5b9a\u4f4d\u53c2\u8003 \/ \u88c5\u9970 \/ \u8c03\u8bd5\u7528\u7684 \u2192 \u8bbe <code>visible = false<\/code>\uff1b\u662f\u771f\u6b63\u7684\u6e38\u620f\u5185\u903b\u8f91\u5c42 \u2192 \u7559 <code>visible = true<\/code>\u3002<strong>\u4e0d\u8981<\/strong>\u7ed9\u7f8e\u672f\u8f85\u52a9\u5c42\u8bbe <code>visible = true<\/code> \u2014\u2014 \u4f1a\u7834\u574f\u9504\u5730 \/ \u5730\u5f62\u5224\u5b9a<\/li>\n\n\n\n<li><strong><code>get_breakable_at<\/code> \u4e0d\u67e5 tellable<\/strong>\uff082026-06 \u91cd\u6784\uff09\uff1a\u539f\u672c <code>get_breakable_at<\/code> \u628a tellable \u4e5f\u7b97\u4f5c breakable \u8fd4\u56de\uff0c\u5bfc\u81f4\u65a7\u5934\u5728 Afforest \u4e0a\u80fd range \u51fa\u6765\u6253\u6389\u3002\u91cd\u6784\u6210 <code>get_breakable_at<\/code> \u8df3\u8fc7 <code>BreakableTellable<\/code>\uff08\u4fdd\u6301&#8221;building&#8221;\u8bed\u4e49\uff09\uff0c\u65b0\u589e <code>get_tellable_at(at_position) -&gt; BreakableTellable<\/code> \u7ed9\u9504\u5934\u4e13\u7528\u3002\u5171\u4eab\u626b\u63cf\u903b\u8f91\u62bd\u5230\u79c1\u6709 <code>_find_breakable_at(at_position, skip_tellable)<\/code><\/li>\n\n\n\n<li><strong><code>tellable<\/code> cell = \u6c38\u8fdc\u53ef\u9504<\/strong>\uff082026-06\uff0c<code>get_current_tile_can_hoe<\/code>\uff09\uff1atellable \u5143\u6570\u636e\u7684 cell \u4e0d\u7ba1 tile \u5728\u4e0d\u5728\u3001TileSet \u4e0b\u5c42\u662f\u4ec0\u4e48 tile \u7c7b\u578b\u2014\u2014<strong>\u6c38\u8fdc\u53ef\u9504<\/strong>\uff08\u9664\u975e\u88ab\u519c\u7530\/axe\/building \u5360\u7528\uff09\u3002\u7531 <code>Level.tellable_broken_cells: Dictionary&lt;layer_key, Array&lt;Vector2i&gt;&gt;<\/code> \u8bb0\u5f55\u88ab\u64e6\u7684 cell\uff08\u4e0e <code>BuildingResource.tellable_broken_cells<\/code> \u540c\u6784\u2014\u2014\u5185\u5b58\u89c6\u56fe + \u6301\u4e45\u5316\u5171\u4eab\u7ed3\u6784\uff09\u3002layer_key \u683c\u5f0f <code>\"&lt;scene_file_path&gt;:&lt;layer_name&gt;\"<\/code>\uff0c\u73a9\u5bb6\u7ad9\u5728\u8fd9\u4e9b cell \u4e0a\u5373\u4f7f tile \u5df2\u64e6\u4e5f\u59cb\u7ec8\u7b97\u53ef\u9504\u3002\u8bbe\u8ba1\u610f\u56fe\uff1aAfforest \u7b49\u88c5\u9970 tile \u64e6\u6389\u5c31\u89e3\u9501\u4e00\u5757\u53ef\u8015\u5730\uff0c\u7ed5\u5f00 TileSet \u914d\u7f6e\u9650\u5236<\/li>\n\n\n\n<li><strong>.tres \u5b57\u6bb5\u7f3a\u5931\u9677\u9631<\/strong>\uff1a<code>sword.tres<\/code> \u548c <code>plates03.tres<\/code> \u6ca1\u663e\u5f0f\u58f0\u660e <code>type<\/code> \u5b57\u6bb5\uff0c\u52a0\u8f7d\u540e type \u662f enum \u9ed8\u8ba4 0\uff08Weapon\uff09\u2014\u2014\u8fd9\u662f\u4e2a\u6f5c\u5728 bug\uff0c<strong>\u65b0\u589e .tres \u65f6\u52a1\u5fc5\u663e\u5f0f\u58f0\u660e <code>type<\/code> \u5b57\u6bb5<\/strong>\uff0c\u4e0d\u8981\u4f9d\u8d56 enum \u9ed8\u8ba4<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Resource \/ Character<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>character_resource.gd:energy_floor<\/code> \u9ed8\u8ba4\u503c\u5fc5\u987b\u662f <code>0.0<\/code><\/strong>\uff1afloor \u8868\u8fbe&#8221;\u5df2\u6c38\u4e45\u6263\u9664\u7684\u4f53\u529b&#8221;\uff0c\u5f00\u5c40\u5e94\u8be5\u662f 0\u3002<strong>\u4e0d\u8981<\/strong>\u6539\u56de <code>1<\/code> \u6216\u4efb\u4f55\u975e\u96f6\u503c\u2014\u2014<code>update_stamina<\/code> 1 \u79d2\u540e\u4f1a\u628a current clamp \u5230 <code>ceiling = max - floor<\/code>\uff0c\u975e\u96f6\u9ed8\u8ba4\u503c\u4f1a\u8ba9\u80fd\u91cf\u6761\u4e00\u5f00\u5c40\u5c31\u663e\u793a\u4e0d\u6ee1\u3002\u8be6\u89c1 AGENTS.md \u00a71 &#8220;<code>character_resource.gd:energy_floor<\/code> \u9ed8\u8ba4\u503c\u5751&#8221;<\/li>\n\n\n\n<li><strong><code>.tres<\/code> \u91cc Resource \u5b50\u5b57\u6bb5\u8981\u663e\u5f0f\u58f0\u660e\uff0c\u4e0d\u8981\u5168\u9760\u4ee3\u7801\u9ed8\u8ba4<\/strong>\uff1a<code>resources\/character_resource.tres<\/code> \u5386\u53f2\u4e0a\u5b8c\u5168\u6ca1\u5199 <code>energy_max\/current\/floor<\/code> \u4e09\u4e2a\u5b57\u6bb5\uff0c\u52a0\u8f7d\u65f6\u5168\u7528 <code>character_resource.gd<\/code> \u91cc\u7684\u9ed8\u8ba4\u3002\u5982\u679c\u9ed8\u8ba4\u503c\u6539\u4e86\uff08\u6bd4\u5982\u8fd9\u6b21 floor \u4ece 1 \u6539 0\uff09\uff0c\u65e7 .tres \u6ca1\u6709&#8221;\u58f0\u660e\u4e86\u4ec0\u4e48 \/ \u7528\u4e86\u9ed8\u8ba4&#8221;\u7684\u6982\u5ff5\uff0c\u52a0\u8f7d\u987a\u5e8f\u654f\u611f\u5bb9\u6613\u8e29\u5751\u3002\u65b0\u5efa\/\u6539 .tres \u65f6<strong>\u663e\u5f0f\u58f0\u660e\u5173\u952e\u5b57\u6bb5<\/strong>\uff0c\u907f\u514d\u9690\u6027\u4f9d\u8d56\u4ee3\u7801\u9ed8\u8ba4\u503c<\/li>\n\n\n\n<li><strong>Web \u6a21\u5f0f <code>.tres<\/code> \u6539\u52a8\u4e0d\u4f1a\u81ea\u52a8\u540c\u6b65\u5230 user:\/\/ \u955c\u50cf<\/strong>\uff1a<code>WebSaveAdapter.SEED_RUNTIME_PATHS<\/code> \u5728 cold-start \u628a\u6e90 .tres \u62f7\u8d1d\u5230 <code>user:\/\/runtime_state\/<\/code>\uff0c\u53ea seed \u4e00\u6b21\u3002\u6539\u6e90 .tres \u540e\u6d4f\u89c8\u5668\u91cc\u65e7\u7684\u955c\u50cf\u4ecd\u5b58\u5728\uff08\u503c\u4e0d\u53d8\uff09\u3002\u6e05\u955c\u50cf\uff1a<code>WebSaveAdapter.reset_runtime_state()<\/code> \u6216 <code>_seed_runtime_state_if_needed()<\/code> \u68c0\u67e5\u673a\u5236\u3002\u6539 <code>character_resource.gd<\/code> \u5b57\u6bb5\u9ed8\u8ba4\u503c\u65f6\u5c24\u5176\u6ce8\u610f\u2014\u2014\u6d4f\u89c8\u5668\u7528\u6237\u8dd1\u7684\u5c31\u662f\u955c\u50cf\u7248<\/li>\n\n\n\n<li><strong>floor \u6a21\u578b\u4e0b <code>current<\/code> \u6c38\u8fdc\u7b49\u4e8e <code>ceiling<\/code><\/strong>\uff08\u9664\u975e\u521d\u59cb\u6216\u5403\u98df\u7269\u8ba9 ceiling \u4e0a\u5347\u7684\u77ac\u95f4\uff09\uff1a\u6bcf\u6b21\u5de5\u5177\/\u5efa\u9020\/\u6536\u83b7\u65f6 <code>current -= N; floor += N<\/code>\uff0c\u6240\u4ee5 <code>ceiling = max - floor<\/code> \u4e5f\u540c\u6b65\u964d <code>N<\/code>\u3002\u4efb\u4f55\u4ee3\u7801\u5199 <code>if current &gt;= ceiling: return<\/code> \u90fd\u4f1a\u88ab floor &gt; 0 \u65f6\u9519\u8bef\u89e6\u53d1\u2014\u2014\u89c6\u89c9\u4e0a\u73a9\u5bb6\u770b\u5230 12.5% \u89c9\u5f97&#8221;\u5feb\u6ca1\u7535&#8221;\uff0c\u5b88\u536b\u5374\u5f53\u4f5c&#8221;\u5df2\u6ee1 ceiling&#8221;\u62e6\u6389\u64cd\u4f5c\u3002<strong>\u6b63\u786e\u5b88\u536b<\/strong>\uff1a\u9884\u6d4b <code>future_current = min(new_ceiling, current + delta)<\/code>\uff0c<code>if future_current &lt;= current: return<\/code>\u3002\u8be6\u89c1 AGENTS.md \u00a71 &#8220;\u6ee1\u4f53\u529b\u5b88\u536b&#8221;\u548c&#8221;\u5b8c\u6574\u8303\u5f0f&#8221;\u3002\u8fd9\u6761\u662f 2026-06 \u4fee consume_food \u65f6\u6316\u51fa\u6765\u7684 floor \u6a21\u578b\u8bbe\u8ba1\u9677\u9631<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">7. \u5173\u952e\u6587\u4ef6\u7d22\u5f15<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u4e3b\u9898<\/th><th>\u6587\u4ef6<\/th><\/tr><\/thead><tbody><tr><td>\u4efb\u52a1\u8d44\u6e90\u5b9a\u4e49<\/td><td><code>structs\/task_resource.gd<\/code><\/td><\/tr><tr><td>\u4efb\u52a1 UI<\/td><td><code>compoents\/character\/children\/attribute\/children\/task\/task.gd<\/code><\/td><\/tr><tr><td>\u4f53\u529b\u8d44\u6e90<\/td><td><code>structs\/character_resource.gd<\/code><\/td><\/tr><tr><td>\u4f53\u529b UI \/ \u5de5\u5177\u6d88\u8017 \/ \u7d2f\u762b\u5bf9\u8bdd\u89e6\u53d1<\/td><td><code>compoents\/character\/children\/attribute\/children\/statusinfo\/statusinfo.gd<\/code><\/td><\/tr><tr><td>\u89d2\u8272\u8f93\u5165 + \u8dd1\u6b65\u673a\u5236 + \u5403\u98df\u7269<\/td><td><code>compoents\/character\/character.gd<\/code><\/td><\/tr><tr><td>\u96e8\u58f0<\/td><td><code>managers\/cutscene_manager\/cutscene_manager.gd<\/code><\/td><\/tr><tr><td>BGM<\/td><td><code>managers\/sound_manager\/sound_manager.gd<\/code><\/td><\/tr><tr><td>\u5267\u60c5 trigger \u5206\u53d1<\/td><td><code>scenes\/game\/game.gd<\/code>\uff08<code>load_level<\/code> \u5185 <code>level_loaded.emit()<\/code> \u4e4b\u540e\uff09<\/td><\/tr><tr><td>wuninghouse cutscene<\/td><td><code>levels\/wuninghouse\/wuninghouse_cutscene.gd<\/code><\/td><\/tr><tr><td>wuninghouse \u706f\u5149\u95ea\u70c1<\/td><td><code>levels\/wuninghouse\/wuninghouse.gd<\/code><\/td><\/tr><tr><td>wuninghouse_alf \u706f\u5149\u95ea\u70c1 + sleep area<\/td><td><code>levels\/wuninghouse_alf\/wuninghouse_alf.gd<\/code><\/td><\/tr><tr><td>wuninghouse_corridor \u706f\u5149\u95ea\u70c1 + TransferArea \u504f\u79fb<\/td><td><code>levels\/wuninghouse_corridor\/wuninghouse_corridor.gd<\/code><\/td><\/tr><tr><td>\u8d70\u5eca \u2192 wuningroom \u5355\u6b21\u5bf9\u8bdd\u95e8<\/td><td><code>levels\/wuninghouse_corridor\/wuninghouse_corridor_wuningromm.gd<\/code><\/td><\/tr><tr><td>silver_mist \u7ed3\u5c40\u9762\u677f\uff08trigger 7\u21928\uff09<\/td><td><code>levels\/silver_mist\/silver_mist_cutscene.gd<\/code><\/td><\/tr><tr><td>\u4efb\u52a1\u8d44\u6e90\u6587\u4ef6<\/td><td><code>resources\/task\/*.tres<\/code>\uff08101 \/ 1001\uff09<\/td><\/tr><tr><td>\u5546\u5e97\u8d44\u6e90<\/td><td><code>resources\/shop\/npc{2001,4001,4002,4003}_shop_resource.tres<\/code><\/td><\/tr><tr><td>\u8303\u56f4\u63d0\u793a\uff08\u5de5\u5177 range grid \u663e\u793a + \u4f53\u529b\u5f52\u96f6\u62e6\u622a\uff09<\/td><td><code>compoents\/range_prompt\/range_prompt.gd<\/code><\/td><\/tr><tr><td>\u5de5\u5177\u6548\u679c\u57fa\u7c7b\uff08\u542b <code>consumes_energy()<\/code> \u62bd\u8c61\uff09<\/td><td><code>structs\/hold_effect_resource.gd<\/code><\/td><\/tr><tr><td>\u9504\u5730\/\u6d47\u6c34\/\u780d\u6811\u6548\u679c\uff08override <code>consumes_energy()=true<\/code>\uff09<\/td><td><code>compoents\/character\/hold_effect\/7001.gd<\/code> \/ <code>7002.gd<\/code> \/ <code>7003.gd<\/code><\/td><\/tr><tr><td>\u5efa\u9020\u6548\u679c\u57fa\u7c7b\uff08<code>BuildingHoldEffectResourceBase<\/code>\uff09<\/td><td><code>compoents\/character\/hold_effect\/8001.gd<\/code><\/td><\/tr><tr><td>\u79cd\u5b50\u6548\u679c\u57fa\u7c7b\uff08<code>SeedHoldEffectResourceBase<\/code>\uff09<\/td><td><code>compoents\/character\/hold_effect\/4001.gd<\/code><\/td><\/tr><tr><td>\u5251\u653b\u51fb\u6548\u679c<\/td><td><code>compoents\/character\/hold_effect\/1001.gd<\/code><\/td><\/tr><tr><td>\u624b\u6301\u680f\uff08\u542b\u5207\u5de5\u5177\u629b\u5149\uff09<\/td><td><code>compoents\/character\/children\/attribute\/children\/hold\/hold.gd<\/code><\/td><\/tr><tr><td>\u7d2f\u762b\u5bf9\u8bdd\uff08\u4f53\u529b\u5f52\u96f6\u89e6\u53d1\uff09<\/td><td><code>dialogic\/timeline\/Alf_stamina_deplete.dtl<\/code><\/td><\/tr><tr><td>NPC 1001\uff08\u8239\u592b\uff09\u5bf9\u8bdd<\/td><td><code>dialogic\/timeline\/npc1001_prompt.dtl<\/code><\/td><\/tr><tr><td>NPC 2001\uff08\u5e97\u4e3b\uff09\u5bf9\u8bdd<\/td><td><code>dialogic\/timeline\/npc2001_prompt.dtl<\/code><\/td><\/tr><tr><td>NPC 4001\/4002\/4003\uff08silver_mist \u4e09\u5e97\u4e3b\uff09\u5bf9\u8bdd<\/td><td><code>dialogic\/timeline\/npc{4001,4002,4003}_prompt.dtl<\/code><\/td><\/tr><tr><td>WuningHouse \u4e3b\u5267\u60c5\u5bf9\u8bdd<\/td><td><code>dialogic\/timeline\/wuning_house_pro00_*.dtl<\/code><\/td><\/tr><tr><td><code>@tool<\/code> \u7f16\u8f91\u5668 TileMap \u5bfc\u51fa\u5de5\u5177<\/td><td><code>levels\/MapCapture.gd<\/code><\/td><\/tr><tr><td>\u8df3\u5b98\u7f51\u4e34\u65f6\u6309\u94ae<\/td><td><code>scenes\/game\/canvas_layer.gd<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\u6a21\u5757 \/ \u8d44\u6e90 \/ API \u901f\u67e5\uff08\u8865\u5168\uff09<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">\u4e0b\u9762\u8fd9\u5f20\u8868\u662f\u7ed9\u65b0\u4eba\u548c Agent \u7528\u7684\u300c\u5730\u56fe\u300d\uff1a\u6bcf\u4e2a autoload\u3001struct\u3001component\u3001level \u90fd\u80fd\u5728\u8fd9\u91cc\u5b9a\u4f4d\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">8. Autoload \u603b\u89c8<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u6ce8\u518c\u987a\u5e8f\uff08<code>project.godot<\/code> \u7684 <code>[autoload]<\/code>\uff0c\u6309\u5f15\u64ce\u5b9e\u4f8b\u5316\u987a\u5e8f\uff09\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>#<\/th><th>\u540d\u79f0<\/th><th>\u6765\u6e90<\/th><th>\u804c\u8d23<\/th><\/tr><\/thead><tbody><tr><td>1<\/td><td>PhantomCameraManager<\/td><td><code>addons\/phantom_camera<\/code><\/td><td>2D \u76f8\u673a\u7ba1\u7406\uff08addon\uff09<\/td><\/tr><tr><td>2<\/td><td>Dialogic<\/td><td><code>addons\/dialogic<\/code><\/td><td>\u5bf9\u8bdd\u7cfb\u7edf\uff08addon\uff09<\/td><\/tr><tr><td>3<\/td><td>Cursor<\/td><td><code>addons\/awesome_custom_cursor<\/code><\/td><td>\u81ea\u5b9a\u4e49\u5149\u6807\uff08addon\uff09<\/td><\/tr><tr><td>4<\/td><td><strong>CutsceneManager<\/strong><\/td><td><code>managers\/cutscene_manager<\/code><\/td><td>\u5267\u60c5\u72b6\u6001 \/ \u96e8\u58f0 \/ sprint \u95e8\u7981<\/td><\/tr><tr><td>5<\/td><td><strong>GameManager<\/strong><\/td><td><code>managers\/game_manager<\/code><\/td><td>\u5168\u5c40\u6e38\u620f\u603b\u63a7 \/ quit \/ save \u6d41\u7a0b<\/td><\/tr><tr><td>6<\/td><td><strong>SceneManager<\/strong><\/td><td><code>managers\/scene_manager<\/code><\/td><td>Loading \u8fc7\u6e21\u5207\u573a\u666f<\/td><\/tr><tr><td>7<\/td><td><strong>PromptManager<\/strong><\/td><td><code>managers\/prompt_manager<\/code><\/td><td>\u4efb\u52a1\u5956\u52b1\u5f39\u7a97 <code>start_celebrate<\/code><\/td><\/tr><tr><td>8<\/td><td><strong>SoundManager<\/strong><\/td><td><code>managers\/sound_manager<\/code><\/td><td>BGM + \u52a8\u4f5c\u97f3\u6548\u6c60<\/td><\/tr><tr><td>9<\/td><td><strong>UtilsManager<\/strong><\/td><td><code>managers\/utils_manager<\/code><\/td><td>\u5750\u6807\/\u671d\u5411\/drop_pickable\/start_shop<\/td><\/tr><tr><td>10<\/td><td><strong>LoadingManager<\/strong><\/td><td><code>managers\/loading_manager<\/code><\/td><td>ColorRect+AnimationPlayer \u52a0\u8f7d\u8fc7\u6e21<\/td><\/tr><tr><td>11<\/td><td><strong>ResourceManager<\/strong><\/td><td><code>managers\/resource_manager<\/code><\/td><td>Resource \u52a0\u8f7d\/\u4fdd\u5b58\u7edf\u4e00\u5165\u53e3<\/td><\/tr><tr><td>12<\/td><td><strong>WebSaveAdapter<\/strong><\/td><td><code>managers\/web_save_adapter<\/code><\/td><td>Web\/\u684c\u9762\u5b58\u6863\u8def\u5f84\u9002\u914d + <code>swap_to_runtime_deep<\/code><\/td><\/tr><tr><td>13<\/td><td>ImGuiRoot<\/td><td><code>addons\/imgui-godot<\/code><\/td><td>\u7f16\u8f91\u5668 ImGui \u8c03\u8bd5\uff08addon\uff09<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">9. Manager API \u901f\u67e5<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">CutsceneManager\uff08\u5267\u60c5\u72b6\u6001 + \u96e8\u58f0\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u4fe1\u53f7<\/strong>\uff1a\u65e0<\/li>\n\n\n\n<li><strong>\u5e38\u91cf<\/strong>\uff1a<code>RAIN_DB=-8.0<\/code>\u3001<code>RAIN_FADE_OUT_SEC=10.0<\/code>\u3001<code>RAIN_FADE_IN_SEC=1.0<\/code>\u3001<code>RAIN_SILENCE_DB=-25.0<\/code><\/li>\n\n\n\n<li><strong>\u516c\u5f00\u65b9\u6cd5<\/strong>\uff1a<\/li>\n\n\n\n<li><code>_process(_delta)<\/code> \u2014 \u6839\u636e <code>cutscene_trigger<\/code> \u81ea\u52a8\u64ad\/\u505c\u96e8\u58f0\uff081~4 \u64ad\u653e\uff1b5 \u6de1\u51fa\uff09<\/li>\n\n\n\n<li><code>stop_rain()<\/code> \u2014 \u4e3b\u52a8 10s \u6e10\u505c<\/li>\n\n\n\n<li><code>pause_rain_immediately()<\/code> \u2014 \u786c\u505c + <code>_manually_paused=true<\/code>\uff08incident \u89c6\u9891\u7528\uff09<\/li>\n\n\n\n<li><code>resume_rain()<\/code> \u2014 \u590d\u4f4d <code>_manually_paused<\/code> + \u6e10\u5165<\/li>\n\n\n\n<li><code>fade_stop_rain(duration = 10.0)<\/code> \u2014 \u81ea\u5b9a\u4e49\u65f6\u957f\u6e10\u505c\uff0c\u53ef await<\/li>\n\n\n\n<li><code>can_sprint() -&gt; bool<\/code> \u2014 <code>cutscene_trigger &gt; 6<\/code>\uff08\u89d2\u8272 sprint \u95e8\u7981\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">GameManager\uff08\u5168\u5c40\u603b\u63a7\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u4fe1\u53f7<\/strong>\uff1a<code>quit<\/code><\/li>\n\n\n\n<li><strong>\u5bfc\u51fa<\/strong>\uff1a<code>game: Game<\/code>\u3001<code>setting_resource: SettingResource<\/code>\u3001<code>archive_resource_list: Array[String]<\/code><\/li>\n\n\n\n<li><strong>\u516c\u5f00\u65b9\u6cd5<\/strong>\uff1a<\/li>\n\n\n\n<li><code>on_quit()<\/code> \u2014 emit quit\uff1bsave_setting\uff1bWeb \u8d70 <code>WebSaveAdapter._persist_all<\/code>\uff0c\u684c\u9762\u8d70 <code>_persist_runtime_state<\/code> + <code>get_tree().quit()<\/code><\/li>\n\n\n\n<li><code>save_to_archives()<\/code> \u2014 \u517c\u5bb9 pause_menu\/main \u7684\u65e7\u5165\u53e3\uff0c\u5185\u90e8\u8d70 <code>_persist_runtime_state<\/code><\/li>\n\n\n\n<li><code>get_archive_resource_list() -&gt; Array[String]<\/code> \u2014 \u7ed9 <code>_persist_all<\/code> \u7528<\/li>\n\n\n\n<li><code>pause()<\/code> \/ <code>resume()<\/code> \u2014 <code>get_tree().paused = true\/false<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">SceneManager\uff08\u573a\u666f\u5207\u6362\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u4fe1\u53f7<\/strong>\uff1a<code>scene_changed(scene: Scene)<\/code><\/li>\n\n\n\n<li><strong>\u679a\u4e3e<\/strong>\uff1a<code>Scene { Main, Game, Prologue }<\/code><\/li>\n\n\n\n<li><strong>\u5e38\u91cf<\/strong>\uff1a<code>SCENE_NAME = { Main, Game, Prologue }<\/code> \u2192 \u8def\u5f84<\/li>\n\n\n\n<li><strong>\u516c\u5f00\u65b9\u6cd5<\/strong>\uff1a<code>switch_scene(scene, center = Vector2(0.5,0.5))<\/code> \u2014 \u5185\u90e8\u8d70 <code>LoadingManager.enter \u2192 \u5f02\u6b65\u52a0\u8f7d \u2192 add_child \u2192 LoadingManager.leave<\/code>\uff0c\u6574\u4e2a\u94fe\u6761 await \u5728 autoload \u5185\u4e0d\u88ab\u622a\u65ad<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">PromptManager\uff08\u5956\u52b1\u5f39\u7a97\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u5b57\u6bb5<\/strong>\uff1a<code>is_celebrate: bool<\/code>\uff08\u4efb\u52a1\u5f39\u7a97\u663e\u793a\u671f\u95f4 true\uff09<\/li>\n\n\n\n<li><strong>\u516c\u5f00\u65b9\u6cd5<\/strong>\uff1a<code>start_celebrate(label, inventory_list: Array[Dictionary])<\/code> \u2014 \u5148 <code>character.add_inventory(item['inventory'], item['count'])<\/code> \u53d1\u5956\u52b1\uff0c\u518d instantiate <code>Celebrate<\/code> \u8282\u70b9 \u2192 await <code>celebrate.finish<\/code> \u2192 queue_free<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">SoundManager\uff08BGM + \u97f3\u6548\u6c60\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u679a\u4e3e<\/strong>\uff1a<code>AudioType<\/code>\uff08walk \u8349\/\u77f3\u591a\u6863\u3001chest \u5f00\/\u5173\u591a\u6863\u3001axe\/hoe \u5404\u6863\u3001page_turner\u3001unlocking\u3001rain\uff09\u3001<code>AudioGrade<\/code>\uff08None + \u5404 walk\/chest \u5b50\u96c6\uff09<\/li>\n\n\n\n<li><strong>\u5bfc\u51fa<\/strong>\uff1a<code>audio_List: Array[AudioStream]<\/code>\u3001<code>pool_size: int = 10<\/code>\u3001<code>back_level_audio_list: Array[Dictionary]<\/code>\uff08\u6309 <code>Game.LevelType<\/code>\uff09<\/li>\n\n\n\n<li><strong>\u516c\u5f00\u65b9\u6cd5<\/strong>\uff1a<\/li>\n\n\n\n<li><code>fill_pool()<\/code> \u2014 \u521d\u59cb\u5316 player pool<\/li>\n\n\n\n<li><code>player_audio(audio_tpye, volume=0.0, from=0.0, grade=None)<\/code> \u2014 \u62ff\u7a7a\u95f2 player \u64ad\u653e<\/li>\n\n\n\n<li><code>stop_grade(grade)<\/code> \u2014 \u505c\u6389\u8be5 grade \u7684\u6240\u6709 player<\/li>\n\n\n\n<li><code>get_free_player()<\/code> \u2014 pool \u53d6\u7a7a\u95f2\uff0c\u65e0\u5219 new \u4e00\u4e2a<\/li>\n\n\n\n<li><code>play_level_audio(level)<\/code> \u2014 \u968f\u673a\u9009\u9996 \u2192 \u65e7 1s \u6de1\u51fa \u2192 \u65b0 2s \u6de1\u5165<\/li>\n\n\n\n<li><code>stop_level_audio()<\/code> \u2014 <code>CutsceneManager.fade_stop_rain(2.0)<\/code> + \u505c back_audio<\/li>\n\n\n\n<li><code>pause_bgm_immediately()<\/code> \/ <code>resume_bgm()<\/code> \u2014 \u89c1 \u00a74<\/li>\n\n\n\n<li><code>play_level_audio_loop(level)<\/code> \/ <code>play_level_audio_by_name(level_name)<\/code> \u2014 \u534f\u7a0b\u5faa\u73af\u64ad + \u6309\u540d\u7279\u5316\uff08wuninghouse \u4e09\u4e2a\u8d70 Silent Rain Narrative\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">UtilsManager\uff08\u6742\u9879\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u5185\u90e8\u7c7b<\/strong>\uff1a<code>ScreenPositionResult { position, canvas_position, is_on_screen }<\/code><\/li>\n\n\n\n<li><strong>\u516c\u5f00\u65b9\u6cd5<\/strong>\uff1a<\/li>\n\n\n\n<li><code>get_screen_position(node) -&gt; ScreenPositionResult<\/code> \u2014 \u5c4f\u5e55\u5f52\u4e00\u5316\u5750\u6807\uff08offset -12px\uff09<\/li>\n\n\n\n<li><code>get_render_size() -&gt; Vector2<\/code><\/li>\n\n\n\n<li><code>transform_position_tile(at) -&gt; Vector2i<\/code> \u2014 16px \u7f51\u683c\u5438\u9644<\/li>\n\n\n\n<li><code>get_direction_from_position(at, target)<\/code> \u2014 \u8fd4\u56de <code>Front\/Back\/Left\/Right<\/code><\/li>\n\n\n\n<li><code>drop_pickable(inventory, count, at_position)<\/code> \u2014 \u4e16\u754c\u6389\u843d\u7269<\/li>\n\n\n\n<li><code>start_shop(shop_resource)<\/code> \u2014 <code>await shop.finish<\/code> \u540e <code>queue_free<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">LoadingManager\uff08\u52a0\u8f7d\u8fc7\u6e21\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u516c\u5f00\u65b9\u6cd5<\/strong>\uff1a<\/li>\n\n\n\n<li><code>enter_force()<\/code> \/ <code>leave_force()<\/code> \u2014 \u76f4\u63a5\u8bbe shader_parameter\/progress<\/li>\n\n\n\n<li><code>enter(center, invent=false, callback)<\/code> \u2014 \u64ad enter \u52a8\u753b \u2192 await \u2192 callback<\/li>\n\n\n\n<li><code>leave(center, callback)<\/code> \u2014 \u64ad leave \u52a8\u753b \u2192 await \u2192 <code>is_loading=false<\/code> \u2192 callback<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">ResourceManager\uff08\u8d44\u6e90\u52a0\u8f7d\/\u4fdd\u5b58\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u516c\u5f00\u65b9\u6cd5<\/strong>\uff1a<\/li>\n\n\n\n<li><code>load_resource(path) -&gt; Resource<\/code> \u2014 Web \u4f18\u5148\u67e5 <code>WebSaveAdapter.runtime_path(path)<\/code><\/li>\n\n\n\n<li><code>load_resource_async(path, callback, process)<\/code> \u2014 \u5f02\u6b65 + \u8fdb\u5ea6\u56de\u8c03<\/li>\n\n\n\n<li><code>save_resource(resource, custom_path=\"\")<\/code> \u2014 \u9012\u5f52\u628a Resource \u5b50\u5c5e\u6027\u4e00\u5e76 save<\/li>\n\n\n\n<li><code>save_to_archive(resource, archive_name, prop_name)<\/code> \u2014 \u8d70 <code>WebSaveAdapter.archive_file_path<\/code><\/li>\n\n\n\n<li><code>save_runtime(resource)<\/code> \u2014 \u8f6c\u53d1\u5230 <code>WebSaveAdapter.save_runtime<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">WebSaveAdapter\uff08Web\/\u684c\u9762\u5b58\u6863\u8def\u5f84\u9002\u914d\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u5e38\u91cf<\/strong>\uff1a<code>WEB_RUNTIME_ROOT = \"user:\/\/runtime_state\"<\/code>\u3001<code>DESKTOP_ARCHIVE_ROOT = \"res:\/\/archives\"<\/code>\u3001<code>SEED_RUNTIME_PATHS<\/code>\uff08cold-start \u955c\u50cf\u6e05\u5355\uff0c31 \u4e2a .tres\uff1a5 \u4e2a\u5168\u5c40 + 3 \u4e2a character \u5185\u5c42 + 8 \u4e2a\u5173\u5361\u5916\u5c42 + 15 \u4e2a\u5173\u5361\u5185\u5c42 farmland\/fellable_tree\/building\uff09<\/li>\n\n\n\n<li><strong>\u5b57\u6bb5<\/strong>\uff1a<code>is_web: bool<\/code>\uff08<code>_ready<\/code> \u65f6\u6839\u636e <code>OS.has_feature(\"web\")<\/code> \u51b3\u5b9a\uff09<\/li>\n\n\n\n<li><strong>\u516c\u5f00\u65b9\u6cd5<\/strong>\uff1a<\/li>\n\n\n\n<li><code>runtime_path(original_path)<\/code> \u2014 Web \u7aef <code>res:\/\/xxx.tres<\/code> \u2192 <code>user:\/\/runtime_state\/&lt;slot&gt;\/&lt;basename&gt;<\/code><\/li>\n\n\n\n<li><code>save_runtime(resource) -&gt; Error<\/code> \/ <code>load_runtime(path) -&gt; Resource<\/code><\/li>\n\n\n\n<li><code>has_runtime_state() -&gt; bool<\/code> \u2014 \u684c\u9762\u6052 true\uff0cWeb \u770b <code>list_archive_names()<\/code><\/li>\n\n\n\n<li><code>reset_runtime_state()<\/code> \/ <code>reset_slot_runtime_state(slot)<\/code> \u2014 Web \u7aef\u5220\u8fd0\u884c\u65f6\u955c\u50cf<\/li>\n\n\n\n<li><code>archive_root()<\/code> \/ <code>archive_dir_path(name)<\/code> \/ <code>archive_file_path(name, prop)<\/code> \/ <code>open_archive_root()<\/code><\/li>\n\n\n\n<li><code>make_archive_dir(name) -&gt; Error<\/code><\/li>\n\n\n\n<li><code>list_archive_names() -&gt; PackedStringArray<\/code><\/li>\n\n\n\n<li><code>swap_to_runtime(original) -&gt; Resource<\/code> \u2014 \u6d45 swap\uff08\u53ea\u6362\u5916\u5c42\uff09<\/li>\n\n\n\n<li><code>swap_to_runtime_deep(original) -&gt; Resource<\/code> \u2014 \u6df1 swap\uff08\u9012\u5f52\u628a Resource \u5b50\u5c5e\u6027\u4e5f\u5207\u5230\u955c\u50cf\u7248\uff09<\/li>\n\n\n\n<li><code>_persist_all()<\/code> \u2014 quit \u65f6\u904d\u5386 <code>archive_resource_list<\/code> \u8c03 <code>save_resource<\/code><\/li>\n\n\n\n<li>Web \u7aef\u89e6\u53d1\u5668\uff1a<code>_beforeunload<\/code> \/ <code>pagehide<\/code> \/ <code>visibilitychange<\/code> \/ 30s <code>autosave_timer<\/code><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">10. Structs\uff08\u6301\u4e45\u5316\u6570\u636e\u6a21\u578b\uff09<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u7c7b\u540d<\/th><th>\u5173\u952e\u5b57\u6bb5<\/th><th>\u5907\u6ce8<\/th><\/tr><\/thead><tbody><tr><td><code>GameResource<\/code><\/td><td><code>level: Game.LevelType<\/code>\u3001<code>season<\/code>\u3001<code>month\/day\/hour\/minute<\/code>\u3001<code>cutscene_trigger<\/code><\/td><td>\u5168\u5c40\u6e38\u620f\u72b6\u6001\uff08<strong>\u5267\u60c5 trigger \u4e3b\u5b58\u6863<\/strong>\uff09<\/td><\/tr><tr><td><code>CharacterResource<\/code><\/td><td><code>bag: BagResource<\/code>\u3001<code>hold: HoldResource<\/code>\u3001<code>current_hold_select<\/code>\u3001<code>health_max\/current<\/code>\u3001<code>energy_max\/current\/floor<\/code>\u3001<code>money<\/code><\/td><td>\u4f53\u529b floor \u6c38\u4e45\u6263\u9664\u89c1 \u00a71<\/td><\/tr><tr><td><code>BagResource<\/code><\/td><td><code>bag_inventory: Array[Dictionary] = [30 \u4e2a\u7a7a]<\/code><\/td><td><code>{inventory, count}<\/code><\/td><\/tr><tr><td><code>HoldResource<\/code><\/td><td><code>hold_inventory: Array[Dictionary] = [9 \u4e2a\u7a7a]<\/code><\/td><td>\u540c bag \u683c\u5f0f<\/td><\/tr><tr><td><code>Inventory<\/code><\/td><td><code>id, texture, highlight_texture, name, description, type: InventoryType, price, stack, lift, terrain_id=-1, restore_value=0<\/code><\/td><td><code>InventoryType<\/code> \u5343\u4f4d ID \u89c1 \u00a70\u3002<code>terrain_id<\/code> \u4ec5 building \u7528\uff0c<code>restore_value<\/code> \u4ec5 food\/medicine \u7528<\/td><\/tr><tr><td><code>TaskResource<\/code><\/td><td><code>id, promupgator: NPC.NpcType, summary, describe, done, detail: Resource, detail_text, reward, done_signal: StringName<\/code><\/td><td>\u65b9\u6cd5 <code>deal_done\/pay\/complete<\/code>\uff0c\u4fe1\u53f7 <code>done_triggered<\/code><\/td><\/tr><tr><td><code>TaskListResource<\/code><\/td><td><code>list: Array[TaskResource]<\/code>\u3001<code>over_list: Array[int]<\/code><\/td><td>\u5168\u5c40\u4efb\u52a1\u5217\u8868<\/td><\/tr><tr><td><code>CollectTaskDetailResource<\/code><\/td><td><code>list: Array[{inventory, count, has}]<\/code><\/td><td>\u65b9\u6cd5 <code>deal_done\/pay<\/code><\/td><\/tr><tr><td><code>SeedResource<\/code><\/td><td><code>sequence_frame: AtlasTexture, groth_time_state: Array[int], fruit: Inventory<\/code><\/td><td>\u751f\u957f\u5e27 + \u9636\u6bb5\u65f6\u957f\uff08typo: groth\uff09<\/td><\/tr><tr><td><code>FarmlandExistResource<\/code><\/td><td><code>lands: Array[{inventory, moisture, drown_time, cell, position}]<\/code><\/td><td>\u6301\u4e45\u5316\u519c\u7530<\/td><\/tr><tr><td><code>FellableTreeResource<\/code><\/td><td><code>tree_type, whole\/stump\/collapse_altas_*\uff084 \u5b63\u8d34\u56fe\uff09, times, destroy_times, wood<\/code><\/td><td><code>get_whole\/stump\/collapse_atlas(season)<\/code><\/td><\/tr><tr><td><code>FellableTreeExistResource<\/code><\/td><td><code>trees: Array[{fellable_tree, tool_count, position}]<\/code><\/td><td>\u6301\u4e45\u5316\u53ef\u780d\u5bf9\u8c61\u3002<strong>\u517c\u5bb9\u65e7\u5b57\u6bb5 <code>axe_count<\/code><\/strong>\uff08<code>fellable_base.gd:_ready<\/code> \u8fc1\u79fb\u5230 <code>tool_count<\/code>\uff09<\/td><\/tr><tr><td><code>BuildingResource<\/code><\/td><td><code>buildings: Dict&lt;terrain_id, Array[Vector2i]&gt;, chests: Dict&lt;Vector2i, dict&gt;, cell_to_inventory_id: Dict&lt;Vector2i, int&gt;, fence_axe_count: Dictionary, tellable_broken_cells: Dict&lt;layer_key, Array&lt;Vector2i&gt;&gt;<\/code><\/td><td><code>BuildingType<\/code> enum \u5df2\u5e9f\u5f03\u3002<code>cell_to_inventory_id<\/code> \u5b58 Vector2i\u2192inventory.id \u7528\u4e8e\u91cd\u5efa Breakable\uff1b<code>fence_axe_count<\/code> \u5df2\u5e9f\u5f03\u4fdd\u7559\u517c\u5bb9\uff1b<code>tellable_broken_cells<\/code> \u6301\u4e45\u5316\u9504\u5934\u64e6\u6389\u7684 tellable cell\uff08layer_key = <code>&lt;scene_file_path&gt;:&lt;layer_name&gt;<\/code>\uff09\uff0creload \u65f6\u6309\u5b58\u6863\u53cd\u5411 erase_cell \u8fd8\u539f\u64e6\u6389\u72b6\u6001<\/td><\/tr><tr><td><code>ChestResource<\/code><\/td><td><code>colums: int = 4<\/code>\uff08typo\uff09\u3001<code>chest: Array[Dict]<\/code><\/td><td>\u5b9d\u7bb1\u7269\u54c1<\/td><\/tr><tr><td><code>ShopResource<\/code><\/td><td><code>inventory_list: Array[Inventory], columns = 5<\/code><\/td><td>\u5546\u5e97\u914d\u7f6e<\/td><\/tr><tr><td><code>ScheduleResource<\/code><\/td><td><code>type: ScheduleType.Day, start_place, target_place, level: Game.LevelType, hour, end_hour<\/code><\/td><td>\u5b50\u7c7b\u91cd\u5199 <code>update_day_schedule\/finish<\/code><\/td><\/tr><tr><td><code>ScheduleListResource<\/code><\/td><td><code>list: Array[ScheduleResource]<\/code><\/td><td>NPC \u65e5\u7a0b\u96c6\u5408<\/td><\/tr><tr><td><code>HoldEffectResource<\/code><\/td><td><code>false_color, true_color<\/code> + <code>get_range\/update_texture_limit\/get_cell_limit\/play_effect\/has_range_effect\/has_oblique_angle\/has_origin\/consumes_energy<\/code><\/td><td>\u5de5\u5177\u4ea4\u4e92\u8303\u56f4\u57fa\u7c7b\u3002<code>consumes_energy<\/code> \u9ed8\u8ba4 false<\/td><\/tr><tr><td><code>InteractKeyboardResource<\/code><\/td><td><code>keyboard_list: Array[{keyboard, label}]<\/code><\/td><td>UI \u6309\u952e\u63d0\u793a<\/td><\/tr><tr><td><code>LevelResource<\/code><\/td><td><code>last_position, farmland_exist_resource, fellable_tree_exist_resource, building_resource<\/code><\/td><td>\u5173\u5361\u5b58\u6863<\/td><\/tr><tr><td><code>SettingResource<\/code><\/td><td><code>current_existing_index, volume = 0.5<\/code><\/td><td>\u5168\u5c40\u8bbe\u7f6e\uff08slot + \u97f3\u91cf\uff09<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">11. Component API \u901f\u67e5\uff08\u6309\u76ee\u5f55\u5206\u7ec4\uff09<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/character\/\uff08\u73a9\u5bb6\u6838\u5fc3\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>character.gd<\/code><\/strong> \u2014 <code>Character extends CharacterBody2D<\/code><\/li>\n\n\n\n<li>\u4fe1\u53f7\uff1a<code>hoe_target<\/code>\u3001<code>watering_target<\/code>\u3001<code>sickle_target<\/code>\u3001<code>axe_target<\/code>\u3001<code>seed_target<\/code>\u3001<code>building_target<\/code><\/li>\n\n\n\n<li>\u5e38\u91cf\uff1a<code>RUN_COST_PER_SEC=2.0<\/code>\u3001<code>RUN_RECOVER_PER_SEC=1.0<\/code>\u3001<code>RECOVER_DELAY_SEC=1.0<\/code>\u3001<code>PANTING_DURATION_SEC=2.0<\/code>\u3001<code>MAX_STACK_SIZE=64<\/code><\/li>\n\n\n\n<li>\u679a\u4e3e\uff1a<code>ActionState{Default, Lift, OneShot}<\/code>\u3001<code>MovementState{Idle=-1, Walk, Run}<\/code>\u3001<code>FaceDirection{Front=-1, Back, Left}<\/code>\u3001<code>OneShotState{Collect, Hoe, Watering, Axe, Place, Sword}<\/code><\/li>\n\n\n\n<li>\u5173\u952e\u65b9\u6cd5\uff1a<code>is_current_level_indoor()<\/code>\u3001<code>is_interfact_state()<\/code>\u3001<code>get_input_values()<\/code>\u3001<code>distribute_input()<\/code>\u3001<code>movement()<\/code>\u3001<code>set_action_state()<\/code>\u3001<code>set_face_direction()<\/code>\u3001<code>set_movement_state()<\/code>\u3001<code>update_face_direction(p1)<\/code>\u3001<code>update_lift_visible()<\/code>\u3001<code>update_lights_visibility()<\/code>\u3001<code>update_stamina(delta)<\/code>\u3001<code>emit_*_target()<\/code>\u3001<code>on_pickable_enter\/leave(p)<\/code>\u3001<code>on_pick()<\/code> \/ <code>pick_pickable()<\/code>\u3001<code>add_inventory(inv, count)<\/code>\u3001<code>find_exist_item_with_space\/find_exist_item\/find_can_use_item()<\/code>\u3001<code>on_dialogue_timeline_started\/ended<\/code>\u3001<code>on_dialogue_signal_event(dict)<\/code>\u3001<code>on_npc1001_dialogue()<\/code>\u3001<code>to_shop(npc)<\/code>\u3001<code>to_transfer(level)<\/code>\u3001<code>to_buy_inventory(inv, count)<\/code>\u3001<code>selling_inventory(target, count)<\/code>\u3001<code>consume_food()<\/code>\u3001<code>get_energy_ceiling()<\/code>\u3001<code>clamp_energy_to_ceiling()<\/code>\u3001<code>play_walk_sound()<\/code> \/ <code>play_walkatgrass()<\/code><\/li>\n\n\n\n<li><strong><code>_relink_inventory_after_swap()<\/code><\/strong>\uff1aWeb \u6a21\u5f0f deep swap \u540e\u628a BagItem\/HoldItem.current \u91cd\u65b0\u6307\u5411\u65b0 bag\/hold \u7684\u5b57\u5178\uff0c\u907f\u514d\u73a9\u5bb6\u6539 current \u5199\u5230\u65e7 bag<\/li>\n\n\n\n<li><strong><code>children\/interact\/interact.gd<\/code><\/strong> \u2014 <code>Interact extends Control<\/code> \u2014 \u62fe\u53d6\u63d0\u793a <code>KeyboardType {None=-1, Pickable}<\/code><\/li>\n\n\n\n<li><strong><code>children\/animation_state\/animation_state.gd<\/code><\/strong> \u2014 <code>AnimationState extends Node2D<\/code> \u2014 \u5199 BlendTree \u53c2\u6570 + <code>start_one_shot(state)<\/code> await <code>animation_finished<\/code><\/li>\n\n\n\n<li><strong><code>children\/attribute\/attribute.gd<\/code><\/strong> \u2014 <code>Attribute extends CanvasLayer<\/code> \u2014 UI \u603b\u67a2\u7ebd\uff1a<code>get_inventory_node(target)<\/code>\u3001<code>alluishow\/alluihide<\/code><\/li>\n\n\n\n<li><strong><code>children\/attribute\/children\/task\/task.gd<\/code><\/strong> \u2014 <code>Task extends InterfaceNode<\/code><\/li>\n\n\n\n<li>\u4fe1\u53f7\uff1a<code>detail_closed<\/code>\u3001<code>task_closed<\/code><\/li>\n\n\n\n<li>\u679a\u4e3e\uff1a<code>TaskState{Un_Get, Un_Done, Done, Finish}<\/code><\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>save()<\/code>\u3001<code>draw_list()<\/code>\u3001<code>switch()<\/code>\u3001<code>reset()<\/code>\u3001<code>on_click_task_item(task)<\/code>\u3001<code>over_task_from_id\/get_task_from_id\/close_detail\/get_task_state\/to_add_task\/refresh_task_state\/to_over_task\/try_complete_by_signal<\/code><\/li>\n\n\n\n<li><strong><code>children\/attribute\/children\/statusinfo\/statusinfo.gd<\/code><\/strong> \u2014 <code>StatusInfo extends InterfaceNode<\/code><\/li>\n\n\n\n<li>\u76d1\u542c\uff1a<code>hoe_target<\/code>\/<code>watering_target<\/code>\/<code>axe_target<\/code>\/<code>seed_target<\/code>\/<code>building_target<\/code>\uff08\u8be6\u89c1 \u00a71 \u672b\u5c3e\u8868\uff09<\/li>\n\n\n\n<li><code>_process<\/code> \u7ef4\u62a4 GoldCount \/ HealthBar \/ EnergyBar + \u8fb9\u6cbf\u89e6\u53d1\u7d2f\u762b\u5bf9\u8bdd<\/li>\n\n\n\n<li><strong><code>children\/attribute\/children\/bag\/bag.gd<\/code><\/strong> \u2014 <code>Bag extends InterfaceNode<\/code><\/li>\n\n\n\n<li><code>switch()<\/code>\u3001<code>handle_holding_item_on_close()<\/code>\uff08drop-back \u903b\u8f91\uff1a\u539f\u69fd \u2192 \u9996\u4e2a\u7a7a\u69fd \u2192 spawn_pickable\uff09\u3001<code>spawn_pickable(inv, count)<\/code>\u3001<code>reset()<\/code>\u3001<code>set_current_inventory(inv)<\/code><\/li>\n\n\n\n<li><strong><code>children\/attribute\/children\/hold\/hold.gd<\/code><\/strong> \u2014 <code>Hold extends InterfaceNode<\/code><\/li>\n\n\n\n<li>\u5b57\u6bb5\uff1a<code>current_effect: HoldEffectResource<\/code>\u3001<code>allow_click_select: bool<\/code>\u3001<code>allow_scroll: bool<\/code>\u3001<code>_scroll_cooldown<\/code>\u3001<code>SCROLL_COOLDOWN_MS=50<\/code><\/li>\n\n\n\n<li><code>update_current_select(index)<\/code>\u3001<code>update_lift()<\/code>\uff08lift_sprite \u7f29\u653e\u5230 12px\uff09\u3001<code>update_effect()<\/code>\uff08instantiate <code>HoldEffectResource<\/code>\uff0c\u542b\u5207\u5de5\u5177\u629b\u5149\uff09\u3001<code>get_current_select()<\/code>\u3001<code>on_input(event)<\/code>\uff081-9 \/ page_up\/down \u5e26 50ms \u51b7\u5374\uff09<\/li>\n\n\n\n<li><strong><code>children\/attribute\/children\/closet\/closet.gd<\/code><\/strong> \u2014 <code>Closet extends InterfaceNode<\/code> \u2014 <code>switch()<\/code> \u4e0e Bag \u4e92\u65a5<\/li>\n\n\n\n<li><strong><code>children\/attribute\/children\/menu\/menu.gd<\/code><\/strong> \u2014 <code>Menu extends InterfaceNode<\/code><\/li>\n\n\n\n<li><code>on_click_item(item)<\/code> \u2014 Bag\/Task \u4e92\u65a5\uff08\u5e26 0.15s \u5ef6\u8fdf\uff09\uff0c<code>Shop.is_opened<\/code> \u65f6 bail<\/li>\n\n\n\n<li><strong><code>children\/attribute\/children\/task\/children\/task_item\/task_item.gd<\/code><\/strong> \u2014 <code>TaskItem extends InterfaceNode<\/code> \u2014 <code>update_state()<\/code>\u3001<code>on_left_click()<\/code> \u2192 <code>task.on_click_task_item<\/code><\/li>\n\n\n\n<li><strong><code>children\/attribute\/children\/task\/children\/collect_item\/collect_item.gd<\/code><\/strong> \u2014 <code>CollectItem extends InventoryNode<\/code> \u2014 \u663e\u793a <code>has\/count<\/code><\/li>\n\n\n\n<li><strong><code>children\/attribute\/children\/bag\/children\/bag_item\/bag_item.gd<\/code><\/strong> \u2014 <code>BagItem extends InventoryNode<\/code> \u2014 hover \u2192 <code>bag.set_current_inventory<\/code><\/li>\n\n\n\n<li><strong><code>children\/attribute\/children\/hold\/children\/hold_item\/hold_item.gd<\/code><\/strong> \u2014 <code>HoldItem extends InventoryNode<\/code> \u2014 <code>on_left_click<\/code> \u7981\u7528\uff0c<code>on_inventory_click\/right_click<\/code> \u53d7 <code>hold.allow_click_select<\/code> \u63a7\u5236<\/li>\n\n\n\n<li><strong><code>children\/attribute\/children\/menu\/children\/menu_item\/menu_item.gd<\/code><\/strong> \u2014 <code>MenuItem extends InterfaceNode<\/code> \u2014 hover \u5207\u6362 outline_color<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">hold_effect\/ \u5b8c\u6574\u5217\u8868\uff08\u6bcf\u4e2a = \u4e00\u4e2a <code>HoldEffectResource<\/code> \u5b50\u7c7b\uff09<\/h4>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>ID \u6bb5<\/th><th>\u6587\u4ef6<\/th><th>class_name \/ extends<\/th><th>\u884c\u4e3a<\/th><\/tr><\/thead><tbody><tr><td>1001<\/td><td><code>1001.gd<\/code><\/td><td><code>extends HoldEffectResource<\/code><\/td><td>\u5251\u653b\u51fb\uff08\u65e0 range gate\uff0c\u4efb\u610f\u4f4d\u7f6e <code>OneShotState.Sword<\/code>\uff09<\/td><\/tr><tr><td>4001<\/td><td><code>4001.gd<\/code><\/td><td><code>class_name SeedHoldEffectResourceBase<\/code><\/td><td>\u79cd\u5b50\u57fa\u7c7b\uff08<code>emit_seed_target<\/code>\uff09<\/td><\/tr><tr><td>4002~4007<\/td><td><code>4002.gd<\/code> ~ <code>4007.gd<\/code><\/td><td><code>extends SeedHoldEffectResourceBase<\/code><\/td><td>7 \u4e2a\u79cd\u5b50\u7269\u54c1\u5168\u90e8\u590d\u7528 4001 \u57fa\u7c7b<\/td><\/tr><tr><td>7001<\/td><td><code>7001.gd<\/code><\/td><td><code>extends HoldEffectResource<\/code><\/td><td>\u9504\u5934\uff08\u5f00\u57a6\/\u6536\u5272\u6210\u719f\u4f5c\u7269\/\u64e6 Afforest tellable\uff09\u2192 <code>emit_hoe_target<\/code>\uff0c<code>consumes_energy()=true<\/code><\/td><\/tr><tr><td>7002<\/td><td><code>7002.gd<\/code><\/td><td><code>extends HoldEffectResource<\/code><\/td><td>\u6d12\u6c34\u58f6 \u2192 <code>emit_watering_target<\/code>\uff0c<code>consumes_energy()=true<\/code><\/td><\/tr><tr><td>7003<\/td><td><code>7003.gd<\/code><\/td><td><code>extends HoldEffectResource<\/code><\/td><td>\u65a7\u5934\uff08\u780d\u6811\/\u780d\u6805\u680f\uff09\u2192 <code>emit_axe_target<\/code> + camera.shake\uff0c<code>consumes_energy()=true<\/code><\/td><\/tr><tr><td><strong>8001<\/strong><\/td><td><code>8001.gd<\/code><\/td><td><code>class_name BuildingHoldEffectResourceBase<\/code><\/td><td><strong>\u5efa\u9020\u57fa\u7c7b<\/strong>\uff08<code>emit_building_target<\/code>\uff0ccall <code>add_building<\/code>\uff09<\/td><\/tr><tr><td>8002~8024<\/td><td><code>8002.gd<\/code> ~ <code>8024.gd<\/code><\/td><td><code>extends BuildingHoldEffectResourceBase<\/code><\/td><td>23 \u4e2a building \u7269\u54c1\u5168\u90e8\u590d\u7528 8001 \u57fa\u7c7b<\/td><\/tr><tr><td><strong>8025~8055<\/strong><\/td><td><strong>\u4e0d\u5b58\u5728<\/strong><\/td><td>\u2014<\/td><td><strong>id \u6bb5\u7a7a\u7f3a<\/strong>\uff0c\u6ca1\u6709\u5bf9\u5e94 .tres \u4e5f\u6ca1\u6709 hold_effect \u811a\u672c<\/td><\/tr><tr><td>8056~8095<\/td><td><code>8056.gd<\/code> ~ <code>8095.gd<\/code><\/td><td><code>extends BuildingHoldEffectResourceBase<\/code><\/td><td>40 \u4e2a building \u7269\u54c1\u5168\u90e8\u590d\u7528 8001 \u57fa\u7c7b<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">\u5168\u90e8 94 \u4e2a <code>extends BuildingHoldEffectResourceBase<\/code> \u7684\u811a\u672c<strong>\u53ea\u662f\u5355\u884c <code>extends<\/code><\/strong>\uff0839 bytes\uff09\uff0c\u6240\u6709\u884c\u4e3a\u7ee7\u627f\u81ea <code>8001.gd<\/code>\u3002<strong>\u65b0\u52a0 building .tres \u65f6\u4e0d\u9700\u8981\u65b0\u5199 hold_effect<\/strong>\uff0c\u7cfb\u7edf\u4f1a\u6309 id \u81ea\u52a8 instantiate\u3002<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/npc\/\uff08NPC \u884c\u4e3a\u6811\u5bbf\u4e3b\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>npc.gd<\/code><\/strong> \u2014 <code>NPC extends Node2D<\/code><\/li>\n\n\n\n<li>\u4fe1\u53f7\uff1a<code>move_finish<\/code><\/li>\n\n\n\n<li>\u679a\u4e3e\uff1a<code>NpcType { wuning, npc1001, npc2001, npc4001, npc4002, npc4003 }<\/code><\/li>\n\n\n\n<li>\u5e38\u91cf\uff1a<code>NPC_TYPE = { npc1001, npc2001, npc4001, npc4002, npc4003 }<\/code>\uff08<strong>\u5fc5\u987b\u5305\u542b\u6bcf\u4e2a NpcType \u503c<\/strong>\uff0c\u5426\u5219 <code>to_shop<\/code> push_error\uff09<\/li>\n\n\n\n<li>\u5bfc\u51fa\uff1a<code>machine: BTPlayer<\/code>\u3001<code>graphics: Node2D<\/code>\u3001<code>animation_sprite2d: AnimatedSprite2D<\/code>\u3001<code>interact: Control<\/code>\u3001<code>schedule_list_resource: ScheduleListResource<\/code>\uff08\u53ef\u9009\uff09<\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>save()<\/code>\uff08\u4fdd\u5b58 schedule\uff09\u3001<code>to_update_schedule()<\/code>\u3001<code>_on_character_entered\/exited<\/code><\/li>\n\n\n\n<li>Web \u6a21\u5f0f\uff1a<code>_ready<\/code> \u628a schedule_list_resource \u8d70 deep swap<\/li>\n\n\n\n<li><strong>6 \u4e2a\u5b50\u7c7b\uff08\u5168\u90e8\u7a7a\u58f3 <code>extends NPC<\/code>\uff09<\/strong>\uff1a<\/li>\n\n\n\n<li><code>npc\/npc1001\/npc1001.gd<\/code> \u2014 \u8239\u592b<\/li>\n\n\n\n<li><code>npc\/npc2001\/npc2001.gd<\/code> \u2014 village_01 \u5e97\u4e3b<\/li>\n\n\n\n<li><code>npc\/npc4001\/npc4001.gd<\/code> \u2014 silver_mist \u5bb6\u5177\u5e97\u4e3b<\/li>\n\n\n\n<li><code>npc\/npc4002\/npc4002.gd<\/code> \u2014 silver_mist \u98df\u6750\u79cd\u5b50\u5e97\u4e3b<\/li>\n\n\n\n<li><code>npc\/npc4003\/npc4003.gd<\/code> \u2014 silver_mist \u6b66\u5668\u6742\u8d27\u5e97\u4e3b<\/li>\n\n\n\n<li>\u6bcf\u4e2a NPC \u5b50\u573a\u666f\uff08<code>.tscn<\/code>\uff09\u56db\u4ef6\u5957\uff1a<code>.gd<\/code> + <code>_spriteframes.tres<\/code> + \u4e3b\u573a\u666f <code>npc.tscn<\/code> \u5f15\u7528 + \u81ea\u5df1\u7684 BT tree<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/farmland\/farmland.gd<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Farmland extends Node2D<\/code><\/li>\n\n\n\n<li>\u5173\u952e\u65b9\u6cd5\uff1a<code>on_time_update()<\/code>\uff08moisture -= 0.01 + <strong>\u4ec5\u5f53 moisture &gt; 0.5 \u65f6 growth_time++<\/strong>\uff0c\u4e0e wet \u89c6\u89c9\u9608\u503c\u5bf9\u9f50\uff09\u3001<code>to_saw(inventory_node)<\/code>\uff08\u64ad\u79cd\uff09\u3001<code>set_sf()<\/code>\uff08\u6309 <code>groth_time_state<\/code> \u5207\u5e27\uff09\u3001<code>get_frame_from_sequence(at)<\/code>\u3001<code>to_watering()<\/code>\u3001<code>set_moisture()<\/code>\uff08<code>wet.visible = moisture &gt; 0.5<\/code>\uff09\u3001<code>to_sickle()<\/code>\uff08\u6536\u83b7\uff1a\u6210\u719f 2x seed + 3x fruit\uff0c\u534a\u719f 1x seed\uff0c&lt;50% 1x seed\uff09<\/li>\n\n\n\n<li><strong>\u751f\u957f-\u6d47\u6c34\u8054\u52a8<\/strong>\uff082026-06\uff09\uff1a<code>moisture &gt; 0.5<\/code> \u624d\u8ba9 <code>growth_time++<\/code>\uff0c\u6240\u89c1\u5373\u6240\u5f97\u2014\u2014wet \u89c6\u89c9\u5bf9\u5e94\u300c\u5728\u957f\u300d\u3002\u4e0d\u6d47\u6c34 ~50 \u5206\u949f\u540e\uff08moisture 1.0\u21920.5\uff09\u751f\u957f\u6682\u505c\uff0c\u518d\u6d47\u6c34\u6062\u590d<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/fellable_tree\/<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>fellable_base.gd<\/code><\/strong> \u2014 <code>FellableBase extends Node2D<\/code><\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>_on_level_loaded()<\/code>\u3001<code>_on_time_update()<\/code>\uff08\u5b63\u8282\u53d8\u66f4\u5237\u5e27\uff09\u3001<code>set_frame_from_sequence(season=null)<\/code>\uff08whole \u2194 stump\uff09\u3001<code>update_occluder(season=null)<\/code>\u3001<code>update_highlight_area()<\/code>\uff08stump \u540e modulate.a=1.0 \u5e76 queue_free HighlightArea\uff09\u3001<code>to_tool()<\/code>\uff08&#8221;rock&#8221; \u52a8\u753b + \u7d2f\u52a0 tool_count + \u5230 times \u6389 base_drop_count wood\uff0c\u5230 destroy_times \u6389 1 wood \u5e76 <code>remove_fellable_tree<\/code>\uff09<\/li>\n\n\n\n<li>\u679a\u4e3e\uff1a<code>FellableType { FELLABLE_TREE, FELLABLE_MINE }<\/code><\/li>\n\n\n\n<li>\u5b57\u6bb5\u517c\u5bb9\uff1a<code>_ready<\/code> \u91cc <code>if current.has(\"axe_count\") and not current.has(\"tool_count\"):<\/code> \u8fc1\u79fb\u5230 <code>tool_count<\/code><\/li>\n\n\n\n<li><strong><code>fellable_tree_small.gd<\/code><\/strong> \u2014 <code>base_drop_count = 1<\/code>\uff0c<code>to_axe() \u2192 to_tool()<\/code>\uff08<code>to_axe()<\/code> \u662f deprecated alias\uff0c7003.gd \u73b0\u5728\u8c03 <code>to_tool()<\/code>\uff0c\u5bf9\u9f50 <code>Breakable.hit()<\/code> \u62bd\u8c61\uff09<\/li>\n\n\n\n<li><strong><code>fellable_tree_medium.gd<\/code><\/strong> \u2014 <code>base_drop_count = 2<\/code><\/li>\n\n\n\n<li><strong><code>fellable_tree_large.gd<\/code><\/strong> \u2014 <code>base_drop_count = 3<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/fellable_house\/<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>house.gd<\/code><\/strong> \u2014 <code>House extends Node2D<\/code>\uff08\u7a7a\u58f3\uff09<\/li>\n\n\n\n<li><strong><code>adventurer_guild\/adventurer_guild_house_01.gd<\/code><\/strong> \u2014 <code>AdventurerGuildHouse01 extends House<\/code>\uff08\u7a7a\u58f3\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/chest\/<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>chest.gd<\/code><\/strong> \u2014 <code>Chest extends Node2D<\/code><\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>save()<\/code>\uff08<code>is_dynamic<\/code> \u65f6\u8df3\u8fc7\uff09\u3001<code>to_get_resource()<\/code>\u3001<code>to_load_items()<\/code>\u3001<code>ToOpen()<\/code>\uff08layer \u53ef\u89c1 + \u968f\u673a SFX + tween fade-in + \u52a8\u753b + <code>hold.allow_click_select=true<\/code>\uff09\u3001<code>ToClose()<\/code>\uff08\u5bf9\u79f0\uff09\u3001<code>_on_character_entered\/exited<\/code>\uff08\u9000\u51fa\u81ea\u52a8\u5173\uff09<\/li>\n\n\n\n<li>\u5b57\u6bb5\uff1a<code>current_cell: Vector2i<\/code>\uff082026-06 \u65b0\u589e\uff0cadd_chest \/ load_buildings \u65f6\u5199\u5165\uff1bLevel \u76d1\u542c BreakableChest.broken \u65f6\u6309 cell \u627e\u5bf9\u5e94 Chest \u5b50\u8282\u70b9 free\uff09<\/li>\n\n\n\n<li><strong><code>children\/chest_item\/chest_item.gd<\/code><\/strong> \u2014 <code>ChestItem extends InventoryNode<\/code>\uff08\u7a7a\u58f3\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/breakable\/\uff082026-06 \u65b0\u589e\uff1a\u53ef\u7834\u574f\u5efa\u7b51\u901a\u7528\u62bd\u8c61\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>breakable.gd<\/code><\/strong> \u2014 <code>Breakable extends Node2D<\/code> \u901a\u7528\u57fa\u7c7b<\/li>\n\n\n\n<li>\u5b57\u6bb5\uff1a<code>current: Dictionary<\/code>\uff08\u542b <code>cell \/ layer \/ inventory \/ hits_needed \/ tool_count \/ drops \/ drops_count<\/code>\uff09<\/li>\n\n\n\n<li>\u4fe1\u53f7\uff1a<code>broken<\/code>\uff08\u5f7b\u5e95\u7834\u4e86\uff09\u3001<code>progress_changed<\/code>\uff08tool_count \u53d8\uff0c\u53ef\u6302\u8fdb\u5ea6\u6761 UI\uff09<\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>hit(_tool: StringName, drop_position: Vector2)<\/code> \u2014 \u901a\u7528\u5165\u53e3\uff1b\u7d2f\u52a0 tool_count \u2192 \u8fbe hits_needed \u65f6 <code>_on_pre_destroy()<\/code> + drop_pickable + emit broken + queue_free<\/li>\n\n\n\n<li>\u9ed8\u8ba4\u884c\u4e3a\uff1a<code>hits_needed=1<\/code>\u3001<code>drops=\u81ea\u8eab inventory<\/code>\u3001<code>drops_count=1<\/code>\u3001<code>_on_pre_destroy<\/code> \u7a7a\u64cd\u4f5c<\/li>\n\n\n\n<li><strong><code>breakable_fence.gd<\/code><\/strong> \u2014 <code>BreakableFence extends Breakable<\/code>\uff08\u7a7a\u5b50\u7c7b\u5360\u4f4d\uff0c\u672a\u6765 fence \u52a0\u7279\u6b8a\u903b\u8f91\u65f6 override <code>_on_pre_destroy<\/code>\uff09<\/li>\n\n\n\n<li><strong><code>breakable_chest.gd<\/code><\/strong> \u2014 <code>BreakableChest extends Breakable<\/code><\/li>\n\n\n\n<li>\u5b57\u6bb5\uff1a<code>chest_resource_ref: Dictionary<\/code>\uff08\u5f15\u7528 <code>level_resource.building_resource.chests[cell]<\/code>\uff09<\/li>\n\n\n\n<li>override <code>_on_pre_destroy()<\/code>\uff1a\u5148\u628a\u5185\u90e8\u7269\u54c1\u5168\u90e8\u6389\u5230\u5730\u4e0a<\/li>\n\n\n\n<li><strong><code>breakable_bed.gd<\/code><\/strong> \u2014 <code>BreakableBed extends Breakable<\/code>\uff08\u7a7a\u5b50\u7c7b\u5360\u4f4d\uff09<\/li>\n\n\n\n<li><strong><code>breakable_tellable.gd<\/code><\/strong> \u2014 <code>BreakableTellable extends Breakable<\/code>\uff082026-06 \u65b0\u589e\uff09<\/li>\n\n\n\n<li>\u7528\u4e8e\u5e26 <code>metadata\/tellable = true<\/code> \u7684 TileMapLayer\uff08\u5f53\u524d\u662f Afforest\uff09\u7684 tile<\/li>\n\n\n\n<li><strong>override \u6574\u4e2a hit() \u800c\u975e _on_pre_destroy<\/strong>\u2014\u2014\u57fa\u7c7b hit() \u4f1a\u5728 hits_needed \u8fbe\u6210\u65f6\u8c03 <code>UtilsManager.drop_pickable(inventory, ...)<\/code>\uff0ctellable \u6ca1 inventory \u5fc5\u5d29<\/li>\n\n\n\n<li><strong>\u5de5\u5177\u5b88\u536b<\/strong>\uff1a<code>hit(_tool, _drop)<\/code> \u7b2c\u4e00\u884c <code>if _tool != &amp;\"hoe\": return<\/code>\u2014\u2014\u53ea\u6709\u9504\u5934\u80fd\u64e6\u3002\u5176\u4ed6\u5de5\u5177 silent skip<\/li>\n\n\n\n<li>\u547d\u4e2d\u540e\u53ea <code>layer.erase_cell(cell)<\/code>\uff0c\u4e0d drop \u4efb\u4f55\u7269\u54c1\u3001\u4e0d\u5199\u5b58\u6863<\/li>\n\n\n\n<li>\u4e34\u65f6\u673a\u5236\uff0c\u73a9\u5bb6 reload \u540e tile \u4ece\u573a\u666f\u6062\u590d\uff08Level._ready \u65f6\u91cd\u65b0\u626b\u63cf\u6302\u56de\uff09<\/li>\n\n\n\n<li><strong>95 \u4e2a\u5176\u4ed6 inventory \u90fd\u8d70\u9ed8\u8ba4\u57fa\u7c7b<\/strong>\u2014\u2014\u4e0d\u8981\u4e3a\u6bcf\u4e2a inventory \u65b0\u5efa .gd<\/li>\n\n\n\n<li><strong>\u914d\u7f6e\u8868\u96c6\u4e2d\u5728 <code>Level<\/code> \u9876\u90e8 const<\/strong>\uff1a<code>BREAKABLE_SCRIPT_BY_INVENTORY_ID<\/code>\uff08inventory.id \u2192 \u5b50\u7c7b\u811a\u672c\u8def\u5f84\uff09\u3001<code>BREAKABLE_HITS_NEEDED_BY_INVENTORY_ID<\/code>\uff08inventory.id \u2192 \u51e0\u4e0b\u788e\uff0c\u9ed8\u8ba4 1\uff09\u3001<code>_INVENTORY_ID_TO_FILENAME<\/code>\uff08inventory.id \u2192 .tres \u6587\u4ef6\u540d\uff0c<strong>92 \u9879<\/strong> \u4ec5 load_buildings \u7528\uff09<\/li>\n\n\n\n<li><strong>\u65b0\u5de5\u5177\u63a5\u5165<\/strong>\uff08\u5982\u672a\u6765\u52a0 hammer\uff09\uff1aoverride <code>Breakable.hit()<\/code> \u91cc <code>_tool<\/code> \u5206\u652f\uff0c\u6216 override <code>can_break_with(tool) -&gt; bool<\/code>\u3002<strong><code>7003.gd<\/code> \u4e0d\u7528\u52a8<\/strong><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/camera\/camera.gd<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Camera extends Node2D<\/code><\/li>\n\n\n\n<li>\u5e38\u91cf\uff1a<code>ZOOM_INDOOR = 2.0<\/code>\u3001<code>ZOOM_OUTDOOR = 1.8<\/code><\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>set_limit()<\/code>\uff08\u4ece <code>current_level_instance.get_bound()<\/code>\uff09\u3001<code>set_follow_target(character)<\/code>\u3001<code>shake(amplitude=2.0, frequency=3.0, duration=0.1)<\/code>\u3001<code>_check_indoor_and_set_zoom()<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/mouse_focus\/mouse_focus.gd<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>MouseFocus extends Node2D<\/code><\/li>\n\n\n\n<li>\u6bcf\u5e27\uff1aindoor \/ <code>InterfaceNode.above<\/code> \/ \u5bf9\u8bdd\u4e2d\u65f6\u9690\u85cf\uff1b\u5426\u5219 <code>UtilsManager.transform_position_tile(get_global_mouse_position())<\/code> \u7f51\u683c\u5438\u9644<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/range_prompt\/range_prompt.gd<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>RangePrompt extends Node2D<\/code><\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>update_visible()<\/code>\uff08OneShot \/ \u5bf9\u8bdd \/ \u65e0 current_effect \u65f6\u9690\u85cf\uff1b\u4f53\u529b&lt;=0 \u4e14 <code>consumes_energy()<\/code> \u4e5f\u9690\u85cf\uff09\u3001<code>distribute_input()<\/code>\u3001<code>on_left_click()<\/code> \/ <code>deal_hold_action()<\/code>\uff08\u6309 <code>has_range_effect()<\/code> \u5206\u652f\uff0c\u542b\u4f53\u529b\u5b88\u536b\uff09\u3001<code>show_range(range_count)<\/code>\uff08<code>2n+1<\/code> \u7f51\u683c\uff09\u3001<code>set_shader_texture()<\/code>\u3001<code>update_position(force=false)<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/highlight_area\/highlight_area.gd<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>HighlightArea extends Area2D<\/code>\uff08\u5b9e\u9645\u7c7b\u540d\u5e26 typo <code>highlight_are<\/code> \u5b57\u6bb5\u5728 fellable_base \u91cc\u5f15\u7528\uff09<\/li>\n\n\n\n<li><code>_on_character_entered\/exited<\/code> \u2192 tween \u7236 modulate.a 0.3\/1.0 + \u73a9\u5bb6 sprite shader outline_color<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/transfer_area\/transfer_area.gd<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>TransferArea extends Area2D<\/code><\/li>\n\n\n\n<li>\u5b57\u6bb5\uff1a<code>target_level: Game.LevelType<\/code>\u3001<code>is_enter: bool<\/code>\u3001<code>has_finish: bool<\/code>\u3001<code>timer: Timer<\/code><\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>_on_character_entered\/exited<\/code>\uff08\u9000\u51fa\u505c timer + \u6e05 has_finish\uff09\u3001<code>_process(delta)<\/code>\uff08player inside + \u975e\u96f6\u65b9\u5411\u624d tick\uff09\u3001<code>_on_timer_timeout()<\/code> \u2192 <code>GameManager.game.load_level(target_level)<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/pickable\/pickable.gd<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Pickable extends Area2D<\/code><\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>set_size()<\/code>\uff0812px tile\uff09\u3001<code>play_animation()<\/code>\uff080.4s \u5f39\u8df3 + \u5782\u76f4 sine arc\uff09\u3001<code>_on_character_entered\/exited<\/code>\uff08\u7ef4\u62a4 <code>character.pickable_list<\/code>\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/global_light\/global_light.gd<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>GlobalLight extends Node2D<\/code><\/li>\n\n\n\n<li>\u8282\u70b9\uff1a<code>canvas_modulate: CanvasModulate<\/code>\u3001<code>directional_light: DirectionalLight2D<\/code>\u3001<code>shadow_polygon: Polygon2D<\/code><\/li>\n\n\n\n<li>\u5e38\u91cf\uff08\u65f6\u95f4\u5e26\uff09\uff1a<code>DAWN_START=4, DAWN_END=7, MORNING_START=7, MORNING_END=9, DAY_START=9, DAY_END=16, SUNSET_START=16, SUNSET_END=19, DUSK_START=19, DUSK_END=21, NIGHT_START=21, NIGHT_END=4<\/code><\/li>\n\n\n\n<li>\u89d2\u5ea6\u5e38\u91cf\uff1a<code>MORNING_3AM_ROTATION=-90\u00b0<\/code>\u3001<code>NOON_ROTATION=-180\u00b0<\/code>\u3001<code>EVENING_7PM_ROTATION=-270\u00b0<\/code>\u3001<code>MIDNIGHT_ROTATION=-360\u00b0<\/code><\/li>\n\n\n\n<li>\u989c\u8272\/\u80fd\u91cf export\uff1a<code>COLOR_DAWN\/DAY\/SUNSET\/NIGHT<\/code> (HSV)\u3001<code>ENERGY_DAWN=0.1\/DAY=0.2\/SUNSET=0.2\/NIGHT=0.0<\/code><\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>_physics_process<\/code>\uff08\u8ddf\u968f\u89d2\u8272\uff09\u3001<code>_on_time_update()<\/code>\uff08\u975e indoor \u624d\u66f4\u65b0\uff09\u3001<code>_check_indoor_status()<\/code>\uff08hide canvas_modulate + directional_light + shadow_polygon\uff09\u3001<code>update_light_color(hour)<\/code>\uff08\u5206\u6bb5\u7ebf\u6027\u63d2\u503c + max_dist \u5199 shadow shader\uff09\u3001<code>ease_in_out\/is_between\/interpolate_color<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/pause_menu\/pause_menu.gd<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>PauseMenu extends CanvasLayer<\/code><\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>on_click_pause()<\/code>\uff08\u6de1\u5165 + <code>GameManager.pause()<\/code>\uff09\u3001<code>_on_back_to_game_pressed()<\/code>\uff08\u6de1\u51fa + resume\uff09\u3001<code>_on_save_game_pressed()<\/code>\uff08<code>quit.emit()<\/code> + <code>save_to_archives()<\/code>\uff09\u3001<code>_on_setting_pressed()<\/code>\uff08\u5360\u4f4d\uff09\u3001<code>_on_back_to_main_menu_pressed()<\/code>\uff08resume + \u505c level audio + quit + save + <code>SceneManager.switch_scene(Main)<\/code>\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/inventory_node\/inventory_node.gd<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>InventoryNode extends InterfaceNode<\/code>\uff08<strong>\u6240\u6709 bag\/hold\/chest \u69fd\u7684\u57fa\u7c7b<\/strong>\uff09<\/li>\n\n\n\n<li>\u5e38\u91cf\uff1a<code>MAX_STACK_SIZE = 64<\/code>\u3001<code>DOUBLE_CLICK_INTERVAL = 0.3<\/code><\/li>\n\n\n\n<li>\u9759\u6001\u5b57\u6bb5\uff1a<code>holding_item: Dictionary<\/code>\uff08<code>mode = \"left_click\"|\"right_split\"<\/code>\u3001<code>source<\/code>\u3001<code>center<\/code>\uff09\u3001<code>_drag_placed_slots<\/code>\u3001<code>_last_click_time<\/code>\u3001<code>_last_click_slot<\/code><\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>static drop_holding_item()<\/code>\u3001<code>_gui_input(event)<\/code>\uff08\u5904\u7406 Shift+\u5de6\u952e\u8f6c\u79fb \/ \u5355\u51fb \/ \u53f3\u51fb \/ \u53cc\u51fb\uff09\u3001<code>on_shift_click_transfer()<\/code>\u3001<code>find_open_chest()<\/code>\u3001<code>transfer_from_bag_to_chest\/from_hold_to_chest\/from_bag_to_hold\/from_hold_to_bag<\/code>\u3001<code>on_inventory_click(mouse_pos)<\/code>\u3001<code>merge_all_same_items()<\/code>\u3001<code>on_inventory_double_click()<\/code>\u3001<code>on_inventory_right_click()<\/code>\uff08\u534a\u5207\uff09\u3001<code>on_inventory_drag_over()<\/code>\u3001<code>update_display()<\/code>\u3001<code>on_mouse_enter\/exit\/move<\/code>\u3001<code>get_popup_position()<\/code>\u3001<code>place_item()<\/code>\u3001<code>static create_preview_from_data\/close_preview\/update_preview()<\/code><\/li>\n\n\n\n<li><strong>\u5408\u5e76\u89c4\u5219<\/strong>\uff1amerge same-id stacks \u2192 drop \u5230\u9996\u4e2a\u7a7a\u69fd \u2192 \u5426\u5219 swap \u56de <code>holding_item<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/inventory_preview\/inventory_preview.gd<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>InventoryPreview extends CanvasLayer<\/code> \u2014 \u8ddf\u968f\u9f20\u6807\u7684\u6d6e\u52a8\u69fd\uff0c\u6bcf\u5e27\u66f4\u65b0 <code>inventory_node.center<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/inventory_info_popup\/inventory_info_popup.gd<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>InventoryInfoPopup extends CanvasLayer<\/code><\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>set_current_inventory(target)<\/code>\u3001<code>show_popup()<\/code>\uff081.2s \u5ef6\u8fdf + \u6de1\u5165\uff09\u3001<code>hide_popup()<\/code>\uff08\u53d6\u6d88 timer + \u6de1\u51fa\uff09\u3001<code>update_popup(at)<\/code>\uff08clamp \u5230 viewport\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">compoents\/time_recorder\/time_record.gd<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>TimeRecord extends Node2D<\/code><\/li>\n\n\n\n<li>\u4fe1\u53f7\uff1a<code>new_day<\/code>\u3001<code>new_year<\/code>\u3001<code>time_update<\/code>\u3001<code>day<\/code>\uff0806:00\uff09\u3001<code>night<\/code>\uff0821:00\uff09<\/li>\n\n\n\n<li>\u679a\u4e3e\uff1a<code>Season { Spring, Summer, Fall, Winter }<\/code><\/li>\n\n\n\n<li>\u5e38\u91cf\uff1a<code>MONTH_DAYS<\/code>\uff082 \u6708=29 \u5929\uff09\u3001<code>SEASONS<\/code>\uff08\u6708\u2192\u5b63\u8282\uff09<\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>handle_time()<\/code>\uff08level load \u65f6\u540c\u6b65 season\uff09\u3001<code>_on_timer_update()<\/code>\uff08minute++ + \u7ea7\u8054\uff09\u3001<code>update_pointer_rotation()<\/code>\uff08\u5199 label + \u8fb9\u754c emit\uff09\u3001<code>reset_to_january_first()<\/code>\uff08\u5e74 wrap emit <code>new_year<\/code>\uff09\u3001<code>uishow()\/uihide()<\/code><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">12. Levels \/ Scenes API \u901f\u67e5<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">levels\/level.gd\uff08\u5173\u5361\u57fa\u7c7b\uff0c\u6240\u6709 Level \u5b50\u7c7b\u7ee7\u627f\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Level extends Node2D<\/code><\/li>\n\n\n\n<li>\u679a\u4e3e\uff1a<code>LevelLocation { outdoor, indoor }<\/code><\/li>\n\n\n\n<li>\u5bfc\u51fa\uff1a<code>level_resource: LevelResource<\/code>\u3001<code>farmland_layer: TileMapLayer<\/code>\u3001<code>location = outdoor<\/code>\u3001<code>building_layer: TileMapLayer<\/code><\/li>\n\n\n\n<li>\u72b6\u6001\u53d8\u91cf\uff1a<code>farmlands: Array[Farmland]<\/code>\u3001<code>fellable_trees: Array[Node2D]<\/code>\u3001<code>breakables: Array[Breakable]<\/code>\u3001<code>tellable_broken_cells: Dictionary&lt;layer_key, Array&lt;Vector2i&gt;&gt;<\/code>\u3001<code>astar := AStarGrid2D.new()<\/code><\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<\/li>\n\n\n\n<li><code>save()<\/code> \u2014 <code>last_position<\/code> + <code>ResourceManager.save_resource<\/code><\/li>\n\n\n\n<li><code>load_astar()<\/code> \/ <code>load_soild_cell()<\/code>\uff08typo\uff09 \/ <code>mark_static_bodies_as_solid()<\/code> \/ <code>mark_circle_area_as_solid<\/code> \/ <code>mark_rectangle_area_as_solid<\/code><\/li>\n\n\n\n<li><code>get_used_rect()<\/code>\uff08\u6392\u9664 <code>meta(\"bound_exclude\")<\/code>\uff09\u3001<code>get_all_tile_map_layers()<\/code>\uff08\u904d\u5386 <code>TileMapLayerContianer<\/code>\uff09\u3001<code>get_bound()<\/code>\uff08\u5408\u5e76 layers \u7684 world-pixel Rect2i\uff09<\/li>\n\n\n\n<li><code>set_character_postion()<\/code>\uff08typo\uff09\u2014 \u653e\u5728 <code>last_position<\/code> \u6216 <code>$OriginPoint<\/code><\/li>\n\n\n\n<li><strong>tile \u67e5\u8be2<\/strong>\uff1a<code>get_current_tile_can_hoe \/ can_sickle \/ can_axe \/ can_sow \/ can_building \/ has_building<\/code>\u3001<code>get_current_has_farmland<\/code>\u3001<code>get_tellable_at(at)<\/code><\/li>\n\n\n\n<li><strong>\u53ef\u7834\u574f\u5efa\u7b51<\/strong>\uff082026-06 \u65b0\u673a\u5236\uff09\uff1a<code>get_breakable_at(at) -&gt; Breakable<\/code> \/ <code>damage_breakable_at(at, tool)<\/code> \u2014\u2014 axe \u548c\u672a\u6765\u6240\u6709\u5de5\u5177\u8d70 <code>Breakable.hit(tool, at)<\/code> \u7edf\u4e00\u5165\u53e3\u3002<strong><code>axe_fence<\/code> \/ <code>get_current_tile_can_axe_fence<\/code> \u5df2\u5e9f\u5f03<\/strong>\uff08\u4fdd\u7559\u7b7e\u540d\u53ea\u9632&#8221;unknown method&#8221;\u8bef\u62a5\uff09<\/li>\n\n\n\n<li><code>get_terrain_type(at)<\/code> \u2192 &#8220;grass&#8221;\/&#8221;stone&#8221;\/&#8221;road&#8221;\/&#8221;dirt&#8221;\/&#8221;unknown&#8221;<\/li>\n\n\n\n<li>\u519c\u7530\uff1a<code>add_farmland \/ load_exist_farmland \/ get_farmland_from_position \/ get_all_farmland_cells<\/code><\/li>\n\n\n\n<li>\u53ef\u780d\u5bf9\u8c61\uff1a<code>load_exist_fellable_tree<\/code>\uff08\u6309 <code>tree_type<\/code> instantiate\uff09\/ <code>get_fellable_tree_from_position \/ remove_fellable_tree<\/code><\/li>\n\n\n\n<li>\u5bfb\u8def\uff1a<code>get_astar_path_to(start, end, callback)<\/code> \u8fd4\u56de Array[Vector2] cell path\uff08callback \u5f53\u524d\u662f dead code\uff09<\/li>\n\n\n\n<li>\u5efa\u9020\uff1a<code>add_building \/ add_chest \/ create_empty_chest \/ load_buildings<\/code>\uff08add_building \u540c\u6b65\u6302 Breakable\uff1bload_buildings \u904d\u5386 cell_to_inventory_id \u91cd\u5efa\uff09<\/li>\n\n\n\n<li><strong>tellable \u6301\u4e45\u5316<\/strong>\uff082026-06\uff09\uff1a<code>load_tellables \/ _attach_tellable \/ _on_tellable_broken<\/code>\u2014\u2014\u626b\u63cf\u5e26 <code>metadata\/tellable<\/code> \u7684 TileMapLayer \u6302 BreakableTellable\uff1b\u9504\u5934 1 \u4e0b\u64e6 tile + \u5199\u5b58\u6863\uff08<code>BuildingResource.tellable_broken_cells[layer_key]<\/code>\uff09\u3002reload \u65f6\u6309\u5b58\u6863\u53cd\u5411 erase_cell \u8fd8\u539f\u64e6\u6389\u72b6\u6001<\/li>\n\n\n\n<li><strong><code>tellable_broken_cells: Dictionary&lt;layer_key, Array&lt;Vector2i&gt;&gt;<\/code><\/strong>\uff082026-06\uff09\uff1a\u88ab\u9504\u5934\u64e6\u6389\u7684 tellable cell \u5217\u8868\uff0c\u6309 layer \u6807\u8bc6\uff08<code>&lt;scene_file_path&gt;:&lt;layer_name&gt;<\/code>\uff09\u5206\u7ec4\uff1b<code>Level<\/code> \u5185\u5b58\u89c6\u56fe\u4e0e <code>BuildingResource<\/code> \u6301\u4e45\u5316\u5b57\u6bb5\u540c\u6784\u3002<code>get_current_tile_can_hoe<\/code> \u6309\u5f53\u524d layer \u67e5\u5bf9\u5e94 list \u5224\u65ad\u300c\u66fe\u88ab\u64e6\u7684 tellable cell\u300d\u2014\u2014\u73a9\u5bb6\u7ad9\u5728\u8fd9\u4e9b cell \u4e0a\u6c38\u8fdc\u53ef\u9504\uff0c\u7ed5\u5f00 TileSet \u914d\u7f6e\u9650\u5236\u3002<strong>Web \u65e7\u955c\u50cf\u517c\u5bb9<\/strong>\uff1a\u7f3a\u5931\u6b64\u5b57\u6bb5 \u2192 \u52a0\u8f7d\u4e3a <code>{}<\/code> \u2192 \u884c\u4e3a = &#8220;\u6ca1\u64e6\u8fc7\u4efb\u4f55 tile&#8221;\uff08\u7528\u6237\u5df2\u64e6\u7684 tile \u9996\u6b21 reload \u4f1a\u590d\u6d3b\u4e00\u6b21\uff0c\u518d\u64e6\u5c31\u6301\u4e45\u5316\u751f\u6548\uff09<\/li>\n\n\n\n<li><strong>\u9504\u5730 + tellable \u8054\u52a8<\/strong>\uff082026-06\uff0c<code>get_current_tile_can_hoe<\/code>\uff09\uff1a<strong>tellable cell \u6c38\u8fdc\u53ef\u9504<\/strong>\u2014\u2014\u7b2c\u4e00\u4f18\u5148\u904d\u5386\u6240\u6709 <code>metadata\/tellable = true<\/code> \u7684 TileMapLayer\uff1a<\/li>\n\n\n\n<li>\u73a9\u5bb6\u4f4d\u7f6e\u7684 cell \u4e0a tellable tile \u8fd8\u5728 \u2192 \u53ef\u9504<\/li>\n\n\n\n<li>\u73a9\u5bb6\u4f4d\u7f6e\u7684 cell \u4e0a tellable tile \u5df2\u88ab\u780d\u3001\u4e14\u5728 <code>tellable_broken_cells<\/code> \u5217\u8868\u91cc \u2192 \u53ef\u9504<\/li>\n\n\n\n<li>\u5426\u5219\u8d70\u539f\u59cb farmland \u7c7b\u578b\u5224\u65ad\uff08TileSet custom_data <code>farmland = true<\/code>\uff09<\/li>\n\n\n\n<li><strong>\u8bbe\u8ba1\u610f\u56fe<\/strong>\uff1aAfforest \u7b49\u88c5\u9970 tile \u780d\u6389\u5c31\u89e3\u9501\u4e00\u5757\u53ef\u8015\u5730\uff0c\u4e0d\u4f9d\u8d56 TileSet \u4e0b\u5c42 tile \u662f farmland<\/li>\n\n\n\n<li><strong>\u53ef\u7834\u574f\u67e5\u8be2<\/strong>\uff1a<code>get_breakable_at(at_position)<\/code> \u8d70 <code>Breakable<\/code>\uff08\u4e0d\u5047\u8bbe building_layer\uff0c\u6309 <code>current.layer + current.cell<\/code> \u53cd\u67e5\uff0c<strong>\u8df3\u8fc7 <code>BreakableTellable<\/code><\/strong>\u2014\u2014tellable \u662f\u9504\u5934\u4e13\u7528\u901a\u9053\uff0c\u7531 <code>get_tellable_at<\/code> \u72ec\u7acb\u67e5\uff09\uff1b<strong>\u8df3\u8fc7 tile \u5df2\u88ab erase \u7684 breakable<\/strong>\uff08\u76f4\u63a5\u67e5 <code>layer.get_cell_source_id(cell) == -1<\/code>\uff09\u2014\u2014\u6bd4 <code>is_queued_for_deletion()<\/code> \u66f4\u7cbe\u786e\uff08queue_free \u7a97\u53e3\u671f + tile \u72b6\u6001\u662f\u771f\u76f8\u4e4b\u6e90\uff09<\/li>\n\n\n\n<li>Breakable \u79c1\u6709\uff1a<code>_attach_breakable \/ _create_breakable_for \/ _on_breakable_broken \/ _on_breakable_tree_exiting \/ _on_tellable_broken<\/code><\/li>\n\n\n\n<li>\u5e38\u91cf\uff1a<code>BREAKABLE_SCRIPT_BY_INVENTORY_ID<\/code>\uff08inventory.id \u2192 .gd \u8def\u5f84\uff0c4 \u9879\u7279\u4f8b\uff1a8001 fence \/ 8002 chest \/ 8003-8004 bed\uff09\u3001<code>BREAKABLE_HITS_NEEDED_BY_INVENTORY_ID<\/code>\uff08inventory.id \u2192 \u51e0\u4e0b\u788e\uff0c3 \u9879\u7279\u4f8b\uff1a8002=3 \/ 8003-8004=2\uff09\u3001<code>_INVENTORY_ID_TO_FILENAME<\/code>\uff08inventory.id \u2192 .tres \u6587\u4ef6\u540d\uff0c<strong>92 \u9879<\/strong> \u4ec5 load_buildings \u91cd\u5efa\u7528\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">levels\/ \u5b50\u7c7b\u4e00\u89c8<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u7c7b<\/th><th>\u6587\u4ef6<\/th><th>\u5173\u952e\u6269\u5c55<\/th><\/tr><\/thead><tbody><tr><td><code>WuningHouse<\/code><\/td><td><code>wuninghouse\/wuninghouse.gd<\/code><\/td><td>PointLight2D flicker \u7cfb\u7edf\uff08sin + jitter + \u5076\u53d1 spike\uff09\uff0c<code>TransferArea<\/code> \u504f\u79fb\uff08trigger 1~5 \u65f6 y=30\uff09\uff0c<code>$VideoStreamPlayer<\/code>\/<code>$VideoStreamPlayer2<\/code> \u663e\u9690<\/td><\/tr><tr><td><code>WuningHouseAlf<\/code><\/td><td><code>wuninghouse_alf\/wuninghouse_alf.gd<\/code><\/td><td>\u540c\u6b3e flicker\uff1b<code>Sleep<\/code> \u533a\u57df\u6309 pick \u63a8\u8fdb\u4e00\u65e5 + trigger 5\u21926 + <code>load_level(WuningHouseCorridor)<\/code>\uff08\u6d41\u7a0b\u89c1 \u00a72\uff09\uff1bAnimationPlayer <code>cs_pr_pro00_alfroom<\/code> \u89e6\u53d1\u5f00\u573a\u8fc7\u573a\uff1b<code>CutsceneUiShow\/Hide<\/code>\u3001<code>playalfspeak<\/code>\u3001<code>emit_cutscene_trigger<\/code><\/td><\/tr><tr><td><code>WuningHouseCorridor<\/code><\/td><td><code>wuninghouse_corridor\/wuninghouse_corridor.gd<\/code><\/td><td>\u540c\u6b3e flicker\uff1btrigger 5 \u65f6 <code>$TransferArea.x = 30<\/code><\/td><\/tr><tr><td><code>WuningHouseCorridorWuningroom<\/code><\/td><td><code>wuninghouse_corridor\/wuninghouse_corridor_wuningromm.gd<\/code><\/td><td><code>extends TransferArea<\/code>\uff0c\u628a\u4f20\u9001\u66ff\u6362\u6210\u5355\u6b21\u5bf9\u8bdd\u95e8\uff08<code>wuninghouse_corridor_wuningroom.dtl<\/code>\uff09<\/td><\/tr><tr><td><code>SilverMist<\/code><\/td><td><code>silver_mist\/silver_mist.gd<\/code><\/td><td>\u7a7a\u58f3\u3002\u573a\u666f\u5b9e\u4f8b\u5316 npc4001\/4002\/4003\uff08silver_mist \u4e09\u5e97\u4e3b\uff09<\/td><\/tr><tr><td><code>SilverMistCutscene<\/code><\/td><td><code>silver_mist\/silver_mist_cutscene.gd<\/code><\/td><td>over_area \u2192 \u663e\u793a %Over \u7ed3\u5c40\u9762\u677f \u2192 trigger 7\u21928<\/td><\/tr><tr><td><code>Village01<\/code><\/td><td><code>village_01\/village_01.gd<\/code><\/td><td>\u7a7a\u58f3\u3002\u573a\u666f\u5b9e\u4f8b\u5316 npc1001\uff08\u8239\u592b\uff09+ npc2001\uff08\u5e97\u4e3b\uff09<\/td><\/tr><tr><td><code>OldPostRd<\/code><\/td><td><code>old_post_rd\/old_post_rd.gd<\/code><\/td><td>\u7a7a\u58f3<\/td><\/tr><tr><td><code>AdventurerGuildRoom01<\/code><\/td><td><code>adventurer_guild_room_01\/adventurer_guild_room_01.gd<\/code><\/td><td>\u7a7a\u58f3<\/td><\/tr><tr><td><code>Birth<\/code><\/td><td><code>birth\/birth.gd<\/code><\/td><td>\u7a7a\u58f3<\/td><\/tr><tr><td><code>WuningHouseCutscene<\/code><\/td><td><code>wuninghouse\/wuninghouse_cutscene.gd<\/code><\/td><td>\u4e3b\u5267\u60c5\u9a71\u52a8\uff1atrigger 2\u21923\u21924\u21925\u30016\u21927\u3001page \u62fe\u53d6\u3001incident \u89c6\u9891\u3001<code>_populate_gift_container<\/code>\/<code>_grant_gift_rewards<\/code>\u3001<code>_await_any_action<\/code><\/td><\/tr><tr><td><code>WuningHouseAlf.OpenCloset<\/code><\/td><td><code>wuninghouse_alf\/opencloset.gd<\/code><\/td><td>\u8863\u67dc\u89e6\u53d1\u5668\uff08\u6309 chest \u952e\u5f00\u5173\uff09<\/td><\/tr><tr><td><code>GiftResource<\/code><\/td><td><code>wuninghouse\/gift_resource.gd<\/code><\/td><td>Page_gift \u5956\u52b1 bundle\uff08<code>reward: Array[Dict]<\/code>\uff09<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">scenes\/main\/main.gd\uff08\u4e3b\u83dc\u5355\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Main extends Node2D<\/code><\/li>\n\n\n\n<li>\u679a\u4e3e\uff1a<code>MainType { NewGame, Continue, LoadGame, Setting, About, Quit }<\/code><\/li>\n\n\n\n<li>\u5bfc\u51fa\uff1a<code>video: Node2D<\/code>\uff08\u80cc\u666f\u89c6\u5dee\uff09\u3001<code>mouse_sensitivity=0.15<\/code>\u3001<code>max_offset_x=20<\/code>\u3001<code>max_offset_y=12<\/code>\u3001<code>follow_speed=0.01<\/code>\u3001<code>ExistingList: Control<\/code>\u3001<code>continue_button<\/code>\u3001<code>load_game_button<\/code>\u3001<code>existing_buttons: Array[MainButton]<\/code><\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>_process(delta)<\/code>\uff08\u89c6\u5dee\uff09\u3001<code>_ready()<\/code>\uff08\u65e0\u5b58\u6863\u65f6\u7981\u7528 Continue\/LoadGame\uff09\u3001<code>_generate_archive_name()<\/code>\uff08<code>&lt;seq&gt;_MMDD_HHMM<\/code>\uff09\u3001<code>_on_new_game_pressed()<\/code>\uff08\u751f\u6210 slot + desktop \u62f7\u8d1d\u539f\u59cb .tres \u5230 archive\uff09\u3001<code>_on_continue_pressed()<\/code>\uff08\u9009\u6700\u65b0 slot\uff09\u3001<code>_on_load_game_pressed()<\/code>\uff08\u663e\u793a\u5b58\u6863\u5217\u8868\uff09\u3001<code>_on_back_pressed()<\/code>\uff08GameMain\u2194ExistingList\uff09\u3001<code>to_load_existing(index, _new_game=false)<\/code>\u3001<code>_on_quit_pressed()<\/code><\/li>\n\n\n\n<li>\u8c03\u7528\u7684 autoload\uff1a<code>GameManager<\/code>\u3001<code>SceneManager<\/code>\u3001<code>ResourceManager<\/code>\u3001<code>WebSaveAdapter<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">scenes\/game\/game.gd\uff08\u4e3b\u6e38\u620f\u5faa\u73af\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Game extends Node2D<\/code><\/li>\n\n\n\n<li><strong>\u679a\u4e3e<\/strong>\uff1a<code>LevelType { Birth, Village_01, AdventurerGuildRoom_01, SilverMist, OldPostRd, WuningHouse, WuningHouseAlf, WuningHouseCorridor }<\/code><\/li>\n\n\n\n<li><strong>\u5e38\u91cf<\/strong>\uff1a<code>LEVEL_TYPE: Dict[LevelType \u2192 \"&lt;folder&gt;\/&lt;name&gt;\"]<\/code>\uff08<strong>\u952e\u662f\u5c0f\u5199\u5b57\u7b26\u4e32<\/strong>\uff0c\u5982 <code>\"wuninghouse_alf\"<\/code>\uff0c\u4e0d\u662f <code>\"WuningHouseAlf\"<\/code>\uff09<\/li>\n\n\n\n<li>\u5bfc\u51fa\uff1a<code>camera: Camera<\/code>\u3001<code>character: Character<\/code>\u3001<code>inventory_info_popup<\/code>\u3001<code>time_record<\/code>\u3001<code>game_resource: GameResource<\/code>\u3001<code>global_light<\/code>\u3001<code>mouse_focus<\/code>\u3001<code>range_prompt<\/code>\u3001<code>pause_menu<\/code><\/li>\n\n\n\n<li><strong>\u4fe1\u53f7<\/strong>\uff1a<code>level_loaded<\/code>\uff08emit \u65f6\u673a\uff1alevel add_child + character position + camera set_limit\/set_follow + audio start + \u4e00\u5e27 await \u4e4b\u540e\uff09<\/li>\n\n\n\n<li>\u72b6\u6001\u53d8\u91cf\uff1a<code>is_placing_tree<\/code>\u3001<code>current_tree_type<\/code>\u3001<code>current_level_instance: Level<\/code><\/li>\n\n\n\n<li>\u6838\u5fc3\u65b9\u6cd5\uff1a<code>load_level(level: LevelType)<\/code>\u3001<code>switch_season(season, use_loading=true)<\/code>\uff08\u66f4\u65b0 game_resource + \u5207 meta(&#8220;seasonal&#8221;)=true \u7684 TileMapLayer tile_set + <code>set_frame_from_sequence<\/code>\uff09<\/li>\n\n\n\n<li><strong>ImGui \u8c03\u8bd5\u9762\u677f\u5df2\u5e9f\u5f03<\/strong>\uff082026-06 \u5168\u90e8\u4ee3\u7801\u88ab <code>#<\/code> \u6ce8\u91ca\uff09\uff1a\u5305\u62ec Season switch \/ Pickable spawner \/ fellable_tree placement \/ Level Transfer \/ Hour setter \/ Cutscene trigger \/ dialogue tester\u3002<code>_input<\/code> \u7684 <code>WantCaptureMouse<\/code> \u5b88\u536b + <code>is_placing_tree<\/code> \u653e\u7f6e\u6811\u903b\u8f91\u4e5f\u90fd\u5728\u6ce8\u91ca\u5757\u91cc\u3002<strong>\u4e0d\u8981\u6062\u590d\u8fd9\u4e9b\u529f\u80fd\uff0c\u9664\u975e\u6709\u771f\u5b9e\u9700\u6c42<\/strong><\/li>\n\n\n\n<li><strong><code>load_level<\/code> \u5185 LevelType \u5206\u53d1<\/strong>\uff08\u5728 <code>level_loaded.emit()<\/code> \u4e4b\u540e\uff09\uff1a<\/li>\n\n\n\n<li><code>LevelType.Birth<\/code> \u2192 <code>task.try_complete_by_signal(&amp;\"Reach_Birth\")<\/code><\/li>\n\n\n\n<li><code>LevelType.SilverMist &amp;&amp; cutscene_trigger == 7<\/code> \u2192 <code>SoundManager.resume_bgm()<\/code><\/li>\n\n\n\n<li><code>LevelType.WuningHouseAlf &amp;&amp; cutscene_trigger == 1<\/code> \u2192 <code>animation_player.play(\"cs_pr_pro00_alfroom\")<\/code>\uff08\u4ece <code>Cutscene\/AnimationPlayer<\/code> \u8282\u70b9\u53d6\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">scenes\/game\/canvas_layer.gd\uff08<strong>\u4e34\u65f6\u6309\u94ae<\/strong>\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>extends CanvasLayer<\/code><\/li>\n\n\n\n<li><code>const URL = \"https:\/\/alffarmtale.top\/\"<\/code><\/li>\n\n\n\n<li>\u5b50\u8282\u70b9 <code>TextureRect<\/code>\uff08Ver \u6309\u94ae\uff09\u70b9\u51fb \u2192 \u8df3\u5b98\u7f51<\/li>\n\n\n\n<li>Web \u7528 <code>JavaScriptBridge.eval(\"window.open(...)\")<\/code>\uff0c\u684c\u9762\u7528 <code>OS.shell_open()<\/code><\/li>\n\n\n\n<li><strong>\u540c\u65f6\u88ab game.tscn \u548c main.tscn \u5f15\u7528<\/strong>\uff1a\u4e24\u4e2a\u573a\u666f\u7684 CanvasLayer \u8282\u70b9\u90fd\u6302\u8fd9\u4e2a\u811a\u672c\uff0c\u5b50\u8282\u70b9 TextureRect\uff08main \u91cc\u4f4d\u7f6e\/\u8d34\u56fe\u4e00\u6837\uff0c\u4f46\u7528\u6237\u52a0\u4e86\u4e0d\u540c outline shader\uff09\u3002\u811a\u672c\u662f\u901a\u7528\u7684\uff0c\u4e0d\u9700\u8981\u6bcf\u4e2a\u573a\u666f\u5404\u81ea\u590d\u5236<\/li>\n\n\n\n<li><strong>\u672a\u6765\u5220\u9664\u65f6\u628a game.tscn + main.tscn \u91cc CanvasLayer \u4e0b\u7684 Ver\/TextureRect \u5b50\u6811\u548c\u8fd9\u4e2a\u811a\u672c\u4e00\u8d77\u5220\u6389<\/strong>\uff08\u811a\u672c\u91cc\u6709\u6ce8\u91ca\u63d0\u9192\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">levels\/MapCapture.gd\uff08<strong>@tool \u7f16\u8f91\u5668\u5de5\u5177<\/strong>\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>@tool extends ReferenceRect<\/code><\/li>\n\n\n\n<li>\u5bfc\u51fa TileMapLayer \u6574\u5c42\u4e3a PNG\/JPG\uff08\u4fdd\u6301\u539f\u59cb\u50cf\u7d20\uff09<\/li>\n\n\n\n<li>\u5de5\u5177\u6309\u94ae\uff1a<code>1. Setup Capture Area<\/code> \/ <code>2. Export Original Pixels<\/code><\/li>\n\n\n\n<li><strong>\u4e0d\u662f\u5173\u5361\u7c7b\u578b<\/strong>\u2014\u2014\u662f\u8f85\u52a9\u7f8e\u672f\u7684\u7f16\u8f91\u5668\u5de5\u5177\uff0c\u4e0d\u5728 LEVEL_TYPE \/ LevelType enum \u91cc<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">13. \u8d44\u6e90\u76ee\u5f55\u901f\u67e5\uff08Catalog\uff09<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u7269\u54c1\uff08\u6309 InventoryType \u5206\u7ec4\uff0c<strong>\u4ee5\u5b9e\u9645 .tres \u6570\u636e\u4e3a\u51c6<\/strong>\uff09<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Weapon 1000\uff081 \u4e2a\uff09<\/h4>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>ID<\/th><th>\u540d\u79f0<\/th><th>\u4ef7\u683c<\/th><\/tr><\/thead><tbody><tr><td>1001<\/td><td>sword\uff08\u5251\uff09<\/td><td>80<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Material 3000\uff08<strong>\u5b9e\u9645\u65e0 .tres<\/strong>\uff09<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u8be5 ID \u6bb5\u5b9e\u9645\u6ca1\u6709 inventory \u6570\u636e<\/li>\n\n\n\n<li>wood.tres \u5728 <code>medicine\/<\/code> \u76ee\u5f55\uff0ctype=5\uff08Medicine\uff09\uff0cid=3001\uff08\u8be6\u89c1\u4e0b\u6761 bug\uff09<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">\u26a0\ufe0f <code>resources\/inventory\/medicine\/wood.tres<\/code> \u6570\u636e\u4e0d\u4e00\u81f4 bug<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u6587\u4ef6\u8def\u5f84<\/strong>\uff1a<code>medicine\/<\/code>\uff08\u4e0e type \u4e0d\u4e00\u81f4\uff09<\/li>\n\n\n\n<li><strong>id<\/strong>\uff1a<code>3001<\/code>\uff08Material \u6bb5\uff0c\u4e0e type \u4e0d\u4e00\u81f4\uff09<\/li>\n\n\n\n<li><strong>type<\/strong>\uff1a<code>5<\/code>\uff08Medicine = 6000 \u6bb5\uff09<\/li>\n\n\n\n<li><strong>name<\/strong>\uff1a\u6728\u6750<\/li>\n\n\n\n<li><strong>description<\/strong>\uff1a\u539f\u6728\u539f\u6599\uff0c\u5236\u4f5c\u5fc5\u5907<\/li>\n\n\n\n<li><strong>price<\/strong>\uff1a3 \/ <strong>stack<\/strong>\uff1atrue<\/li>\n\n\n\n<li><strong>\u4fee\u590d\u5efa\u8bae<\/strong>\uff1a\u628a\u6587\u4ef6 mv \u5230 <code>medicine\/<\/code> \u4fdd\u7559\uff08\u8def\u5f84\u5bf9\uff09\uff0c\u6539 id \u4e3a 6001 + name \u4e0d\u53d8\u3002<strong>\u6240\u6709\u5f15\u7528\u65b9\u7528 <code>ResourceManager.load_resource(\"res:\/\/resources\/inventory\/medicine\/wood.tres\")<\/code> \u8d70\u8def\u5f84\uff0c\u8def\u5f84\u4e0d\u53d8 id \u600e\u4e48\u6539\u90fd\u80fd\u52a0\u8f7d<\/strong>\u2014\u2014\u8fd9\u662f Uid\/\u8def\u5f84\u89e3\u8026\u7684\u597d\u5904\u3002task 1001 \u7684 detail list \u91cc\u7528 <code>&amp;\"res:\/\/resources\/inventory\/medicine\/wood.tres\"<\/code> \u5f15\u7528\u6240\u4ee5\u8def\u5f84\u6539\u4e0d\u5f97\u3002<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Seed 4000\uff087 \u4e2a\uff0c\u751f\u957f\u9636\u6bb5 [10,20,30] \u79d2\uff09<\/h4>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Seed ID<\/th><th>\u540d\u79f0<\/th><th>\u679c\u5b9e ID<\/th><\/tr><\/thead><tbody><tr><td>4001<\/td><td>\u80e1\u841d\u535c\u79cd\u5b50<\/td><td>5001 carrot<\/td><\/tr><tr><td>4002<\/td><td>\u756a\u8304\u79cd\u5b50<\/td><td>5002 tomato<\/td><\/tr><tr><td>4003<\/td><td>\u8304\u5b50\u79cd\u5b50<\/td><td>5003 eggplant<\/td><\/tr><tr><td>4004<\/td><td>\u5377\u5fc3\u83dc\u79cd\u5b50<\/td><td>5004 cabbage<\/td><\/tr><tr><td>4005<\/td><td>\u5c0f\u9ea6\u79cd\u5b50<\/td><td>5005 wheat<\/td><\/tr><tr><td>4006<\/td><td>\u5357\u74dc\u79cd\u5b50<\/td><td>5006 pumpkin<\/td><\/tr><tr><td>4007<\/td><td>\u5c0f\u9ec4\u74dc\u79cd\u5b50<\/td><td>5007 cucumber<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Food 5000\uff088 \u4e2a\uff09<\/h4>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>ID<\/th><th>\u540d\u79f0<\/th><th>\u4ef7\u683c<\/th><th>restore_value<\/th><\/tr><\/thead><tbody><tr><td>5000<\/td><td>apple\uff08\u82f9\u679c\uff09<\/td><td>2<\/td><td>5<\/td><\/tr><tr><td>5001<\/td><td>carrot\uff08\u80e1\u841d\u535c\uff09<\/td><td>3<\/td><td>5<\/td><\/tr><tr><td>5002<\/td><td>tomato\uff08\u756a\u8304\uff09<\/td><td>4<\/td><td>6<\/td><\/tr><tr><td>5003<\/td><td>eggplant\uff08\u8304\u5b50\uff09<\/td><td>4<\/td><td>6<\/td><\/tr><tr><td>5004<\/td><td>cabbage\uff08\u5377\u5fc3\u83dc\uff09<\/td><td>3<\/td><td>8<\/td><\/tr><tr><td>5005<\/td><td>wheat\uff08\u5c0f\u9ea6\uff09<\/td><td>2<\/td><td>4<\/td><\/tr><tr><td>5006<\/td><td>pumpkin\uff08\u5357\u74dc\uff09<\/td><td>4<\/td><td>10<\/td><\/tr><tr><td>5007<\/td><td>cucumber\uff08\u5c0f\u9ec4\u74dc\uff09<\/td><td>4<\/td><td>7<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u4ef7\u683c 2~4\uff0c\u6062\u590d\u91cf 4~10\uff0c\u4e0e\u4ef7\u683c\u6b63\u76f8\u5173\u3002<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Medicine 6000\uff08\u5b9e\u9645\u53ea\u6709 1 \u4e2a\u9519\u4f4d\u7684 wood\uff09<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u89c1\u4e0a\u6761 bug<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Tool 7000\uff083 \u4e2a\uff09<\/h4>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>ID<\/th><th>\u540d\u79f0<\/th><th>\u4ef7\u683c<\/th><th>stack<\/th><th>lift<\/th><\/tr><\/thead><tbody><tr><td>7001<\/td><td>hoe\uff08\u9504\u5934\uff09<\/td><td>35<\/td><td>false<\/td><td>false<\/td><\/tr><tr><td>7002<\/td><td>sprinkler\uff08\u6d12\u6c34\u58f6\uff09<\/td><td>30<\/td><td>false<\/td><td>false<\/td><\/tr><tr><td>7003<\/td><td>axe\uff08\u65a7\u5934\uff09<\/td><td>60<\/td><td>false<\/td><td>false<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Crop 8000\uff08\u5b9e\u9645\u65e0 .tres\uff09<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>enum \u6ce8\u91ca\u8bf4&#8221;\u4f5c\u7269 8000&#8243;\uff0c\u4f46\u5b9e\u9645\u6240\u6709 id=8001~8095 \u7684 .tres \u90fd\u662f type=8 (Building)<\/li>\n\n\n\n<li>Crop \u7c7b\u578b\u5f53\u524d\u6ca1\u6709\u4efb\u4f55\u7269\u54c1<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Building 8000 \u6bb5\uff08\u5b9e\u9645 92 \u4e2a .tres\uff0ctype=8\uff09<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">\u6309\u5b50\u7c7b\u522b\u5206\u7ec4\uff08\u4e0d\u5168\u5b8c\u6574\uff0c\u4ec5\u5217\u4e3b\u8981\uff09\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u5b50\u7c7b\u522b<\/th><th>id \u6bb5<\/th><th>\u6570\u91cf<\/th><\/tr><\/thead><tbody><tr><td>fence \/ chest<\/td><td>8001~8002<\/td><td>2<\/td><\/tr><tr><td>bed<\/td><td>8003~8004<\/td><td>2<\/td><\/tr><tr><td>bonsai<\/td><td>8005~8007<\/td><td>3<\/td><\/tr><tr><td>book<\/td><td>8008~8011<\/td><td>4<\/td><\/tr><tr><td>bowl \/ candle \/ plate \/ pork \/ knife \/ clock \/ chinese_cabbage<\/td><td>8012~8013, 8071, 8075, 8056, 8020, 8019<\/td><td>7<\/td><\/tr><tr><td>chair<\/td><td>8014~8018<\/td><td>5<\/td><\/tr><tr><td>closet<\/td><td>8021~8023<\/td><td>3<\/td><\/tr><tr><td>foods\uff08\u76d8\u5b50\u88c5\u98df\u7269\uff09<\/td><td>8024~8055<\/td><td>32<\/td><\/tr><tr><td>paintings<\/td><td>8057~8060, 8064~8070<\/td><td>11\uff08<strong>8061~8063 \u7f3a\u53f7<\/strong>\uff09<\/td><\/tr><tr><td>plates<\/td><td>8072~8074<\/td><td>3<\/td><\/tr><tr><td>seasoner\uff08\u8c03\u5473\u7f50\uff09<\/td><td>8076~8082<\/td><td>7<\/td><\/tr><tr><td>sofa<\/td><td>8083~8088<\/td><td>6<\/td><\/tr><tr><td>table<\/td><td>8089<\/td><td>1<\/td><\/tr><tr><td>toilet<\/td><td>8090~8093<\/td><td>4<\/td><\/tr><tr><td>tv<\/td><td>8094~8095<\/td><td>2<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u603b\u8ba1 92 \u9879<\/strong>\uff08\u7f3a\u53f7 8061\/8062\/8063\uff09\u3002Building .tres \u7684 <code>terrain_id<\/code> \u5b57\u6bb5\u5fc5\u987b\u624b\u52a8\u67e5 <code>used\/tileset\/building\/building.tres<\/code> \u586b\u6b63\u786e\u503c\uff0c\u4e0d\u8981\u590d\u5236 <code>id - 8001<\/code>\uff08\u8be6\u89c1 \u00a76\uff09\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u4efb\u52a1\uff08TaskResource\uff09<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>ID<\/th><th>summary<\/th><th>\u89e6\u53d1\u65b9\u5f0f<\/th><th>\u5956\u52b1<\/th><\/tr><\/thead><tbody><tr><td>101<\/td><td>\u6d77\u9e25\u5c9b\u65e7\u519c\u573a\u4ee3\u7ba1<\/td><td><code>done_signal = &amp;\"Reach_Birth\"<\/code>\uff08\u5230\u8fbe Birth \u5173\u89e6\u53d1\uff09<\/td><td>10\u00d7 cabbage_seed<\/td><\/tr><tr><td>1001<\/td><td>\u8239\u592b\u7684\u8bf7\u6c42<\/td><td>\u5bf9\u8bdd\u5185\u4fe1\u53f7 <code>over_task<\/code>\uff08\u6536\u96c6 1 axe + 20 wood\uff09<\/td><td>4\u00d7 carrot_seed + 4\u00d7 tomato_seed<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">\u53ef\u780d\u5bf9\u8c61\uff08FellableTreeResource\uff09<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u5927\u5c0f<\/th><th>times\uff08\u6811\u6869\uff09\/ destroy_times\uff08\u6d88\u5931\uff09<\/th><th>\u6bcf\u6b21\u6389\u843d<\/th><\/tr><\/thead><tbody><tr><td>small<\/td><td>3 \/ 4<\/td><td>1 wood<\/td><\/tr><tr><td>medium<\/td><td>4 \/ 6<\/td><td>2 wood<\/td><\/tr><tr><td>large<\/td><td>6 \/ 9<\/td><td>3 wood<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">\u5546\u5e97\uff08ShopResource\uff09\u2014 <strong>\u5171 4 \u4e2a\uff0c\u6309\u5e97\u4e3b\u5206\u7c7b<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u6587\u4ef6<\/th><th>\u5e97\u4e3b NPC<\/th><th>\u5185\u5bb9<\/th><th>\u5907\u6ce8<\/th><\/tr><\/thead><tbody><tr><td><code>npc2001_shop_resource.tres<\/code><\/td><td>npc2001\uff08village_01\uff09<\/td><td>axe, hoe, sprinkler, sword, carrot, carrot_seed<\/td><td>\u901a\u7528\u5de5\u5177\u5e97\u3002columns=5<\/td><\/tr><tr><td><code>npc4001_shop_resource.tres<\/code><\/td><td>npc4001\uff08silver_mist\uff09<\/td><td><strong>\u5168\u90e8 92 \u4e2a building \u7269\u54c1<\/strong><\/td><td>\u5bb6\u5177\u5e97\u3002columns=5<\/td><\/tr><tr><td><code>npc4002_shop_resource.tres<\/code><\/td><td>npc4002\uff08silver_mist\uff09<\/td><td>8 Food + 7 Seed<\/td><td>\u98df\u6750\u79cd\u5b50\u5e97\u3002columns=5<\/td><\/tr><tr><td><code>npc4003_shop_resource.tres<\/code><\/td><td>npc4003\uff08silver_mist\uff09<\/td><td>sword + wood + axe\/hoe\/sprinkler<\/td><td>\u6b66\u5668\u6742\u8d27\u5e97\u3002columns=5<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u5356\u4ef7\u7edf\u4e00 = <code>max(int(price * 0.8), 1)<\/code>\uff08<code>shop_item<\/code> \u5356\u51fa\u8ba1\u7b97\uff09<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">NPC \u65e5\u7a0b\uff08ScheduleResource\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>npc2001_work.tres<\/code>\uff1a9~18 \u65f6\uff0crest \u2192 work<\/li>\n\n\n\n<li><code>npc2001_rest.tres<\/code>\uff1a18~9 \u65f6\uff0cwork \u2192 rest\uff08\u8986\u76d6\u5230\u6b21\u65e5\uff09<\/li>\n\n\n\n<li><code>npc2001_schedule_list_resource.tres<\/code>\uff1a\u5f53\u524d\u6fc0\u6d3b\u7684\u65e5\u7a0b\uff08\u52a8\u6001\u8ffd\u52a0 rest\uff09<\/li>\n\n\n\n<li>npc4001\/4002\/4003 <strong>\u6682\u65e0 schedule<\/strong>\uff08silver_mist \u573a\u666f\u91cc\u4e0d\u79fb\u52a8\uff0cschedule_list_resource \u53ef\u4e0d\u6302\uff09<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u5bf9\u8bdd\uff08Dialogic timeline\uff09<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u6587\u4ef6<\/th><th>\u89d2\u8272 \/ \u98ce\u683c<\/th><th>\u5185\u5bb9<\/th><\/tr><\/thead><tbody><tr><td><code>Alf_stamina_deplete.dtl<\/code><\/td><td>Alf \/ bubble<\/td><td>\u4f53\u529b\u5f52\u96f6\u63d0\u793a\uff08\u8be6\u89c1 \u00a71\uff09<\/td><\/tr><tr><td><code>npc1001_prompt.dtl<\/code><\/td><td>NPC 1001 \/ bubble<\/td><td>\u8239\u592b\u63a5\u4efb\u52a1 + \u5173\u5361\u8f6c\u79fb\uff08birth \u2194 village_01\uff09<\/td><\/tr><tr><td><code>npc2001_prompt.dtl<\/code><\/td><td>NPC 2001 \/ speaker<\/td><td>\u5546\u5e97\u5bf9\u8bdd\uff08&#8221;\u6211\u8981\u4e70\u70b9\u4e1c\u897f&#8221;\u5f00 Shop\uff09<\/td><\/tr><tr><td><code>npc4001_prompt.dtl<\/code><\/td><td>NPC 4001 \/ speaker<\/td><td>silver_mist \u5bb6\u5177\u5e97\u4e3b\uff08&#8221;\u6211\u8981\u4e70\u70b9\u4e1c\u897f&#8221;\u2192 <code>[signal {npc:\"3\", type:\"shop\"}]<\/code>\uff09<\/td><\/tr><tr><td><code>npc4002_prompt.dtl<\/code><\/td><td>NPC 4002 \/ speaker<\/td><td>silver_mist \u98df\u6750\u79cd\u5b50\u5e97\u4e3b\uff08\u2192 <code>[signal {npc:\"4\", type:\"shop\"}]<\/code>\uff09<\/td><\/tr><tr><td><code>npc4003_prompt.dtl<\/code><\/td><td>NPC 4003 \/ speaker<\/td><td>silver_mist \u6b66\u5668\u6742\u8d27\u5e97\u4e3b\uff08\u2192 <code>[signal {npc:\"5\", type:\"shop\"}]<\/code>\uff09<\/td><\/tr><tr><td><code>wuning_house_pro00_01.dtl<\/code><\/td><td>Alf \/ bubble<\/td><td>\u5f00\u5934\u72ec\u767d\uff1a\u7a97\u5f00\u7740\uff0c\u6587\u4ef6\u4f1a\u88ab\u96e8\u6dcb<\/td><\/tr><tr><td><code>wuning_house_pro00_02.dtl<\/code><\/td><td>Alf \/ bubble<\/td><td>\u6536\u62fe\u623f\u95f4\u7684\u8a93\u8a00<\/td><\/tr><tr><td><code>wuning_house_pro00_02_1.dtl<\/code><\/td><td>Alf \/ bubble<\/td><td>&#8220;\u5979\u8fd8\u6ca1\u51c6\u5907\u597d&#8221;<\/td><\/tr><tr><td><code>wuning_house_pro00_03.dtl<\/code><\/td><td>Alf \/ bubble<\/td><td>\u6253\u788e\u76d8\u5b50\u60ca\u614c<\/td><\/tr><tr><td><code>wuning_house_pro00_04.dtl<\/code><\/td><td>Wuning \/ speaker<\/td><td>\u6d77\u9e25\u5c9b\u5931\u8d25\u5f00\u57a6\uff0c\u59d4\u6258 Alf \u4ee3\u7ba1<\/td><\/tr><tr><td><code>wuning_house_pro00_05.dtl<\/code><\/td><td>Wuning \/ speaker<\/td><td>\u96e8\u505c\uff0c\u660e\u65e9 7 \u70b9\u4e1c\u95e8\u51fa\u53d1<\/td><\/tr><tr><td><code>wuning_house_pro00_06.dtl<\/code><\/td><td>Alf \/ speaker<\/td><td>\u79bb\u5bb6\u4e0d\u820d<\/td><\/tr><tr><td><code>wuninghouse_corridor_wuningroom.dtl<\/code><\/td><td>Alf \/ bubble<\/td><td>\u8d70\u5eca\u56de\u5fc6\u88ab\u8bad\u65a5\u7684\u53cd\u601d<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Dialogic character\uff08<code>.dch<\/code>\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>character_bubble.dch<\/code> \/ <code>character_speaker.dch<\/code> \u2014 Alf<\/li>\n\n\n\n<li><code>npc1001_bubble.dch<\/code> \u2014 NPC 1001 \u8239\u592b<\/li>\n\n\n\n<li><code>npc2001_speaker.dch<\/code> \u2014 NPC 2001 \u5e97\u4e3b<\/li>\n\n\n\n<li><code>wuning_bubble.dch<\/code> \/ <code>wuning_speaker.dch<\/code> \u2014 Wuning<\/li>\n\n\n\n<li>\uff08npc4001\/4002\/4003 \u6682\u65e0\u72ec\u7acb .dch\uff0c\u4f7f\u7528 speaker style \u76f4\u63a5\u4ee5 <code>[signal]<\/code> \u89e6\u53d1\u5546\u5e97\uff09<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">14. AI \/ LimboAI \u901f\u67e5<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u884c\u4e3a\u6811\uff08<code>ai\/trees\/<\/code>\uff09<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>BT<\/th><th>NPC<\/th><th>Selector<\/th><\/tr><\/thead><tbody><tr><td><code>npc1001.tres<\/code><\/td><td>\u8239\u592b<\/td><td>\u4e0d\u5728\u8303\u56f4\uff1aidle(back) + \u9690\u85cf interact \u2192 \u5728\u8303\u56f4\uff1aface \u2192 idle facing player \u2192 \u663e\u793a interact \u2192 await <code>dialogue<\/code> \u2192 <code>start_bubble_dialogue(\"npc1001_prompt\")<\/code><\/td><\/tr><tr><td><code>npc2001.tres<\/code><\/td><td>village_01 \u5e97\u4e3b<\/td><td>\u5bfb\u8def\uff08<code>move=true<\/code> \u9690\u85cf interact + <code>move_to_destination(60, contrary=true)<\/code>\uff09 \u2192 \u4e0d\u5728\u8303\u56f4\uff1aidle(back) + \u9690\u85cf interact \u2192 \u5728\u8303\u56f4\uff1aface \u2192 idle facing player \u2192 \u663e\u793a interact \u2192 await <code>dialogue<\/code> \u2192 <code>start_speaker_dialogue(\"npc2001_prompt\")<\/code><\/td><\/tr><tr><td><code>npc4001.tres<\/code><\/td><td>silver_mist \u5bb6\u5177\u5e97\u4e3b<\/td><td>\u540c\u4e0a\u4f46 <code>start_speaker_dialogue(\"npc4001_prompt\")<\/code><\/td><\/tr><tr><td><code>npc4002.tres<\/code><\/td><td>silver_mist \u98df\u6750\u79cd\u5b50\u5e97\u4e3b<\/td><td>\u540c\u4e0a\u4f46 <code>start_speaker_dialogue(\"npc4002_prompt\")<\/code><\/td><\/tr><tr><td><code>npc4003.tres<\/code><\/td><td>silver_mist \u6b66\u5668\u6742\u8d27\u5e97\u4e3b<\/td><td>\u540c\u4e0a\u4f46 <code>start_speaker_dialogue(\"npc4003_prompt\")<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">\u81ea\u5b9a\u4e49 BTAction\uff08<code>ai\/tasks\/<\/code>\uff09<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u6587\u4ef6<\/th><th>\u884c\u4e3a<\/th><\/tr><\/thead><tbody><tr><td><code>await_input.gd<\/code><\/td><td>SUCCESS if <code>Input.is_action_just_pressed(input_key)<\/code> else FAILURE<\/td><\/tr><tr><td><code>calculation_range_face_direction.gd<\/code><\/td><td>\u7b97\u73a9\u5bb6\u2194NPC delta \u2192 \u7ffb <code>npc.graphics.scale.x<\/code>\uff0c\u652f\u6301 <code>contrary<\/code><\/td><\/tr><tr><td><code>move_to_destination.gd<\/code><\/td><td><code>current_level_instance.get_astar_path_to()<\/code> + \u8d70 waypoints + \u64ad <code>walk_&lt;dir&gt;<\/code> + \u5230\u70b9 set <code>move=false<\/code> + emit <code>npc.move_finish<\/code><\/td><\/tr><tr><td><code>play_direction_animation.gd<\/code><\/td><td>\u64ad <code>&lt;animation&gt;_&lt;face_direction&gt;<\/code>\uff08\u9ed1\u677f <code>face_direction<\/code> \u6216 export\uff09<\/td><\/tr><tr><td><code>set_interace_visible.gd<\/code><\/td><td>toggle <code>npc.interact.visible<\/code>\uff08typo: interace\uff09<\/td><\/tr><tr><td><code>start_bubble_dialogue.gd<\/code><\/td><td>\u5207 bubble style + \u6ce8\u518c <code>npc.name.to_lower()+\"_bubble.dch\"<\/code> + \u542f timeline + await <code>timeline_ended<\/code><\/td><\/tr><tr><td><code>start_speaker_dialogue.gd<\/code><\/td><td>\u540c\u4e0a\u4f46 speaker \u98ce\u683c\uff0c\u4e0d\u6ce8\u518c character<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">15. Shop \u6d41\u7a0b\u7ec6\u8282\uff08<code>utils_manager\/children\/shop\/<\/code>\uff09<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>shop.gd<\/code><\/strong> \u2014 <code>Shop extends CanvasLayer<\/code><\/li>\n\n\n\n<li>\u4fe1\u53f7\uff1a<code>finish<\/code><\/li>\n\n\n\n<li>\u9759\u6001\u5b57\u6bb5\uff1a<code>is_opened: bool<\/code><\/li>\n\n\n\n<li>\u5b57\u6bb5\uff1a<code>current_select: ShopItem<\/code>\u3001<code>current_page=1<\/code>\u3001<code>total_pages=1<\/code>\u3001<code>is_sell_mode=false<\/code>\u3001<code>sell_items: Array[Dict]<\/code>\u3001<code>items_per_page=20<\/code><\/li>\n\n\n\n<li>\u65b9\u6cd5\uff1a<code>load_items()<\/code>\uff08\u6309 <code>shop_resource.columns\/%List<\/code> \u521b\u5efa ShopItem\uff09\u3001<code>load_sell_items()<\/code>\uff08\u6536\u96c6 bag + hold_item_list \u975e\u7a7a\u9879\uff09\u3001<code>clear_items()<\/code>\u3001<code>close()<\/code>\uff080.15s \u540c\u65f6 modulate.a\u21920 + scale\u21920.9 \u2192 await finished \u2192 is_opened=false \u2192 \u6062\u590d <code>hold.allow_scroll=true<\/code> \u2192 emit finish\uff09\u3001<code>update_price()<\/code>\uff08sell \u65f6 <code>max(int(price*0.8), 1)<\/code>\uff09\u3001<code>update_current_select(item)<\/code>\u3001<code>set_current_inventory(inventory)<\/code>\u3001<code>_on_buylabel_button_pressed()<\/code> \/ <code>_on_selllabel_button_pressed()<\/code> \/ <code>_on_buy_pressed()<\/code> \u2192 <code>character.to_buy_inventory(inv, count)<\/code> \/ <code>_on_sell_pressed()<\/code> \u2192 <code>character.selling_inventory(target, count)<\/code>\u3001<code>_on_page_up_pressed<\/code> \/ <code>_on_page_down_pressed<\/code>\u3001<code>update_pages_text()<\/code>\u3001<code>update_items_visibility()<\/code>\u3001<code>calculate_total_pages()<\/code><\/li>\n\n\n\n<li><strong><code>shop_item.gd<\/code><\/strong> \u2014 <code>ShopItem extends InventoryNode<\/code> \u2014 <code>update_display()<\/code>\u3001<code>reset()\/set_current()<\/code>\u3001<code>on_left_click()<\/code> \u8c03 super + <code>shop.update_current_select(self)<\/code>\u3001<code>on_inventory_click<\/code> \u7a7a\u5b9e\u73b0\uff08\u4e0d\u80fd\u88ab\u62ff\u8d77\uff09<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">16. \u5b58\u6863\u7cfb\u7edf\u6d41\u7a0b\uff08Web vs \u684c\u9762\uff09<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u684c\u9762\uff08Desktop\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5b58\u6863\u6839\u76ee\u5f55\uff1a<code>res:\/\/archives\/&lt;slot&gt;\/<\/code><\/li>\n\n\n\n<li>\u8def\u5f84\uff1a<code>res:\/\/archives\/&lt;slot&gt;\/&lt;game_resource|bag_resource|hold_resource|...&gt;.tres<\/code><\/li>\n\n\n\n<li><code>ResourceManager.save_resource(resource)<\/code> \u2192 \u76f4\u63a5 <code>ResourceSaver.save(resource.resource_path)<\/code><\/li>\n\n\n\n<li><code>GameManager.on_quit()<\/code> \u2192 <code>_persist_runtime_state<\/code> \u2192 <code>get_tree().quit()<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Web\uff08Web\uff09<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5b58\u6863\u6839\u76ee\u5f55\uff1a<code>user:\/\/runtime_state\/&lt;slot&gt;\/<\/code><\/li>\n\n\n\n<li>cold-start\uff1a<code>SEED_RUNTIME_PATHS<\/code> \u628a 31 \u4e2a\u6838\u5fc3 .tres \u955c\u50cf\u5230 user:\/\/<\/li>\n\n\n\n<li>\u8fd0\u884c\u65f6\uff1a<code>WebSaveAdapter.swap_to_runtime_deep(original)<\/code> \u9012\u5f52\u628a Resource \u5b50\u5c5e\u6027\u5207\u5230\u955c\u50cf\u7248<\/li>\n\n\n\n<li>\u89e6\u53d1\u4fdd\u5b58\uff1a<code>_beforeunload<\/code> \/ <code>pagehide<\/code> \/ <code>visibilitychange<\/code> \/ 30s <code>autosave_timer<\/code><\/li>\n\n\n\n<li><code>GameManager.on_quit()<\/code> \u2192 <code>WebSaveAdapter._persist_all()<\/code> \u2192 \u904d\u5386 <code>archive_resource_list<\/code> \u8c03 <code>save_resource<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u5b58\u6863 slot \u683c\u5f0f<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>&lt;seq&gt;_MMDD_HHMM<\/code>\uff08<code>seq<\/code> \u4ece <code>archive_root<\/code> \u5b50\u76ee\u5f55\u6570 + 1\uff0c<code>MMDD_HHMM<\/code> \u662f\u5f53\u524d\u6708\u65e5\u65f6\u5206\uff09<\/li>\n\n\n\n<li><code>SettingResource.current_existing_index<\/code> \u4fdd\u5b58\u5f53\u524d slot \u540d<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Main \u83dc\u5355\u5b58\u6863\u64cd\u4f5c<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>NewGame\uff1a\u751f\u6210 slot \u2192 desktop \u521b\u5efa archive \u76ee\u5f55 + \u62f7\u8d1d\u539f\u59cb .tres \u2192 <code>to_load_existing<\/code><\/li>\n\n\n\n<li>Continue\uff1a\u9009\u6700\u5927 <code>seq<\/code> slot \u2192 <code>to_load_existing<\/code><\/li>\n\n\n\n<li>LoadGame\uff1a\u5217\u51fa\u6240\u6709 slot\uff0c\u6309 seq \u5012\u5e8f\uff0c\u70b9\u4e86\u518d <code>to_load_existing<\/code><\/li>\n\n\n\n<li>\u65e0\u5b58\u6863\u65f6 Continue\/LoadGame \u6309\u94ae\u81ea\u52a8 disable<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">17. \u52a0\u8f7d\u6d41\u7a0b\u65f6\u5e8f\u56fe\uff08\u6587\u5b57\u7248\uff09<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><code>SceneManager.switch_scene(Game)<\/code> \u2192<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><code>LoadingManager.enter(center, false, _start_scene_load.bind(Game))<\/code> \u2014 \u64ad\u653e enter \u52a8\u753b<\/li>\n\n\n\n<li>await <code>animation_finished<\/code> \u2192 callback<\/li>\n\n\n\n<li><code>_start_scene_load(Game)<\/code> \u2192<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>ResourceManager.load_resource_async(\"res:\/\/scenes\/game\/game.tscn\", callback, process)<\/code><\/li>\n\n\n\n<li>callback: <code>instantiate \u2192 add_child(Game) \u2192 GameManager.game = self \u2192 WebSaveAdapter.swap_to_runtime_deep(game_resource) \u2192 connect GameManager.quit \u2192 save_runtime(game_resource)<\/code><\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Game \u8282\u70b9 <code>_ready<\/code> \u2192 \u9996\u6b21 <code>load_level(initial_level)<\/code> \u2192<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u9996\u6b21\u8d70 <code>LoadingManager.enter_force()<\/code><\/li>\n\n\n\n<li><code>ResourceManager.load_resource_async(level.tscn, ...)<\/code> \u2192\n<ul class=\"wp-block-list\">\n<li><code>level_instance.instantiate() \u2192 if current_level_instance: save + queue_free \u2192 add_child(level_instance) \u2192 set_character_postion \u2192 camera.set_limit \u2192 camera.set_follow_target \u2192 SoundManager.play_level_audio_by_name \u2192 await process_frame \u2192 level_loaded.emit()<\/code><\/li>\n\n\n\n<li>LevelType \u5206\u53d1\uff08Birth \/ SilverMist+7 \/ WuningHouseAlf+1\uff09<\/li>\n\n\n\n<li>callback: <code>await process_frame \u2192 camera.phantom_camera2D.teleport_position \u2192 await process_frame \u2192 LoadingManager.leave(center)<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u540e\u7eed <code>load_level(other)<\/code>\uff1a\u8d70 <code>enter<\/code> \u52a8\u753b\u7248\uff08\u4e0d\u5e26 force\uff09<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>AlfFarmTale \u9879\u76ee\u4e13\u5c5e\u7684\u300c\u5c0f\u6284\u672c\u300d\u3002AI Agent \/ \u65b0\u4eba \/ \u672a\u6765\u7684\u4f60\u8fdb\u9879\u76ee\u65f6\uff0c\u5148\u8bfb\u8fd9\u4e00\u4efd\u3002\u6700 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-604","post","type-post","status-publish","format-standard","hentry","category-developmentlog"],"_links":{"self":[{"href":"https:\/\/alffarmtale.top\/index.php?rest_route=\/wp\/v2\/posts\/604","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alffarmtale.top\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alffarmtale.top\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alffarmtale.top\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/alffarmtale.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=604"}],"version-history":[{"count":2,"href":"https:\/\/alffarmtale.top\/index.php?rest_route=\/wp\/v2\/posts\/604\/revisions"}],"predecessor-version":[{"id":606,"href":"https:\/\/alffarmtale.top\/index.php?rest_route=\/wp\/v2\/posts\/604\/revisions\/606"}],"wp:attachment":[{"href":"https:\/\/alffarmtale.top\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=604"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alffarmtale.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=604"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alffarmtale.top\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=604"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}