published
This commit is contained in:
parent
077d4ab9ac
commit
0f1cb2fe6c
10 changed files with 497 additions and 198 deletions
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "38.00.00",
|
||||
"version": "39.00.00",
|
||||
"css": [
|
||||
"css/base.css",
|
||||
"css/layout.css",
|
||||
|
|
|
|||
280
index.html
280
index.html
|
|
@ -7,11 +7,11 @@
|
|||
<link rel="icon" type="image/png" href="assets/ui/favicon.png?v=16.07.17" />
|
||||
<link rel="apple-touch-icon" href="assets/ui/apple-touch-icon.png?v=16.07.17" />
|
||||
<link rel="shortcut icon" href="favicon.ico?v=16.07.17" />
|
||||
<link rel="stylesheet" href="css/base.css?v=38.00.00" />
|
||||
<link rel="stylesheet" href="css/layout.css?v=38.00.00" />
|
||||
<link rel="stylesheet" href="css/panel.css?v=38.00.00" />
|
||||
<link rel="stylesheet" href="css/components.css?v=38.00.00" />
|
||||
<link rel="stylesheet" href="css/mobile.css?v=38.00.00" />
|
||||
<link rel="stylesheet" href="css/base.css?v=39.00.00" />
|
||||
<link rel="stylesheet" href="css/layout.css?v=39.00.00" />
|
||||
<link rel="stylesheet" href="css/panel.css?v=39.00.00" />
|
||||
<link rel="stylesheet" href="css/components.css?v=39.00.00" />
|
||||
<link rel="stylesheet" href="css/mobile.css?v=39.00.00" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="loadingScreen" class="loading-screen" aria-live="polite">
|
||||
|
|
@ -189,140 +189,140 @@
|
|||
</div>
|
||||
|
||||
<div id="logPushOverlay" class="log-push-overlay" aria-live="polite" aria-atomic="false"></div>
|
||||
<script src="js/version.js?v=38.00.00" defer></script>
|
||||
<script src="js/event_bus.js?v=38.00.00" defer></script>
|
||||
<script src="js/registry_base.js?v=38.00.00" defer></script>
|
||||
<script src="js/disease_registry.js?v=38.00.00" defer></script>
|
||||
<script src="js/sound_pack.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_registry.js?v=38.00.00" defer></script>
|
||||
<script src="js/data.js?v=38.00.00" defer></script>
|
||||
<script src="js/ground_types.js?v=38.00.00" defer></script>
|
||||
<script src="js/input_mode_manager.js?v=38.00.00" defer></script>
|
||||
<script src="js/math.js?v=38.00.00" defer></script>
|
||||
<script src="js/physics_helpers.js?v=38.00.00" defer></script>
|
||||
<script src="js/collision_footprint_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/mechanical_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/constraint_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/assets.js?v=38.00.00" defer></script>
|
||||
<script src="js/audio.js?v=38.00.00" defer></script>
|
||||
<script src="js/perf_profiler.js?v=38.00.00" defer></script>
|
||||
<script src="js/render.js?v=38.00.00" defer></script>
|
||||
<script src="js/sim_core.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_seed_factory.js?v=38.00.00" defer></script>
|
||||
<script src="js/structures.js?v=38.00.00" defer></script>
|
||||
<script src="js/items.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_type_initializers.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_support.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_runtime.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_update_policy.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_dynamic_tool_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_dynamic_ball_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_dynamic_duplicator_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_dynamic_pin_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_dynamic_zunchi_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_dynamic_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_decay_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_growth_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_step_frame.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_step_decay.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_step_dynamic.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_step_growth.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_pipeline.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_runtime.js?v=38.00.00" defer></script>
|
||||
<script src="js/structure_lifecycle.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_render_runtime.js?v=38.00.00" defer></script>
|
||||
<script src="js/ants.js?v=38.00.00" defer></script>
|
||||
<script src="js/health.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_action_spec.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_behavior_state.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_identity_social.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_action_state.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_disease_nest.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_item_effects.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_needs_core.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_behavior_text.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_forced_behavior.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_item_targeting.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_consumable_behavior.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_social_action_runtime.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_building_behavior.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_action_definitions.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_needs_items.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_forced_action_planner_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_action_planner_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_need_planner_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_item_interaction_context.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_food_interaction_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_contact_item_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_item_interaction_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_sunbath_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_cursor_care_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_local_environment_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_social_move_life.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_update_step_frame.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_update_step_ai.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_update_step_environment.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_update_step_movement.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_update_step_health.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_update_pipeline.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_runtime.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_render.js?v=38.00.00" defer></script>
|
||||
<script src="js/world.js?v=38.00.00" defer></script>
|
||||
<script src="js/world_view.js?v=38.00.00" defer></script>
|
||||
<script src="js/family_graph.js?v=38.00.00" defer></script>
|
||||
<script src="js/world_family_social.js?v=38.00.00" defer></script>
|
||||
<script src="js/world_combat_effects.js?v=38.00.00" defer></script>
|
||||
<script src="js/world_environment.js?v=38.00.00" defer></script>
|
||||
<script src="js/world_spatial_budget.js?v=38.00.00" defer></script>
|
||||
<script src="js/world_ants_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/weather_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/item_update_scheduler.js?v=38.00.00" defer></script>
|
||||
<script src="js/simulation_runtime_helpers.js?v=38.00.00" defer></script>
|
||||
<script src="js/tarinai_update_policy.js?v=38.00.00" defer></script>
|
||||
<script src="js/simulation_environment_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/simulation_item_ant_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/simulation_effects_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/simulation_creature_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/simulation_maintenance_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/simulation_ambient_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/simulation_systems.js?v=38.00.00" defer></script>
|
||||
<script src="js/world_update_phases.js?v=38.00.00" defer></script>
|
||||
<script src="js/system_order.js?v=38.00.00" defer></script>
|
||||
<script src="js/simulation.js?v=38.00.00" defer></script>
|
||||
<script src="js/world_update.js?v=38.00.00" defer></script>
|
||||
<script src="js/world_tool_actions.js?v=38.00.00" defer></script>
|
||||
<script src="js/world_placement_log.js?v=38.00.00" defer></script>
|
||||
<script src="js/world_event_effects.js?v=38.00.00" defer></script>
|
||||
<script src="js/command_dispatcher.js?v=38.00.00" defer></script>
|
||||
<script src="js/text_catalog.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_log.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_helpers.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_selected.js?v=38.00.00" defer></script>
|
||||
<script src="js/save_schema.js?v=38.00.00" defer></script>
|
||||
<script src="js/snapshot_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/restore_coordinator.js?v=38.00.00" defer></script>
|
||||
<script src="js/history_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/save_codec.js?v=38.00.00" defer></script>
|
||||
<script src="js/save_storage.js?v=38.00.00" defer></script>
|
||||
<script src="js/save_system.js?v=38.00.00" defer></script>
|
||||
<script src="js/patch_helpers.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_tooltips.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_layout_dialogs.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_ground.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_tools.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_input_shared.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_input_touch.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_input_mouse.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_bind.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_charts.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_family_data.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_family_async.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_family_layout.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_family_paths.js?v=38.00.00" defer></script>
|
||||
<script src="js/ui_family_render.js?v=38.00.00" defer></script>
|
||||
<script src="js/main.js?v=38.00.00" defer></script>
|
||||
<script src="js/debug_tools.js?v=38.00.00" defer></script>
|
||||
<script src="js/version.js?v=39.00.00" defer></script>
|
||||
<script src="js/event_bus.js?v=39.00.00" defer></script>
|
||||
<script src="js/registry_base.js?v=39.00.00" defer></script>
|
||||
<script src="js/disease_registry.js?v=39.00.00" defer></script>
|
||||
<script src="js/sound_pack.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_registry.js?v=39.00.00" defer></script>
|
||||
<script src="js/data.js?v=39.00.00" defer></script>
|
||||
<script src="js/ground_types.js?v=39.00.00" defer></script>
|
||||
<script src="js/input_mode_manager.js?v=39.00.00" defer></script>
|
||||
<script src="js/math.js?v=39.00.00" defer></script>
|
||||
<script src="js/physics_helpers.js?v=39.00.00" defer></script>
|
||||
<script src="js/collision_footprint_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/mechanical_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/constraint_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/assets.js?v=39.00.00" defer></script>
|
||||
<script src="js/audio.js?v=39.00.00" defer></script>
|
||||
<script src="js/perf_profiler.js?v=39.00.00" defer></script>
|
||||
<script src="js/render.js?v=39.00.00" defer></script>
|
||||
<script src="js/sim_core.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_seed_factory.js?v=39.00.00" defer></script>
|
||||
<script src="js/structures.js?v=39.00.00" defer></script>
|
||||
<script src="js/items.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_type_initializers.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_support.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_runtime.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_update_policy.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_dynamic_tool_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_dynamic_ball_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_dynamic_duplicator_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_dynamic_pin_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_dynamic_zunchi_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_dynamic_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_decay_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_growth_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_step_frame.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_step_decay.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_step_dynamic.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_step_growth.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_lifecycle_pipeline.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_runtime.js?v=39.00.00" defer></script>
|
||||
<script src="js/structure_lifecycle.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_render_runtime.js?v=39.00.00" defer></script>
|
||||
<script src="js/ants.js?v=39.00.00" defer></script>
|
||||
<script src="js/health.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_action_spec.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_behavior_state.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_identity_social.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_action_state.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_disease_nest.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_item_effects.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_needs_core.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_behavior_text.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_forced_behavior.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_item_targeting.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_consumable_behavior.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_social_action_runtime.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_building_behavior.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_action_definitions.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_needs_items.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_forced_action_planner_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_action_planner_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_need_planner_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_item_interaction_context.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_food_interaction_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_contact_item_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_item_interaction_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_sunbath_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_cursor_care_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_local_environment_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_social_move_life.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_update_step_frame.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_update_step_ai.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_update_step_environment.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_update_step_movement.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_update_step_health.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_update_pipeline.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_runtime.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_render.js?v=39.00.00" defer></script>
|
||||
<script src="js/world.js?v=39.00.00" defer></script>
|
||||
<script src="js/world_view.js?v=39.00.00" defer></script>
|
||||
<script src="js/family_graph.js?v=39.00.00" defer></script>
|
||||
<script src="js/world_family_social.js?v=39.00.00" defer></script>
|
||||
<script src="js/world_combat_effects.js?v=39.00.00" defer></script>
|
||||
<script src="js/world_environment.js?v=39.00.00" defer></script>
|
||||
<script src="js/world_spatial_budget.js?v=39.00.00" defer></script>
|
||||
<script src="js/world_ants_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/weather_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/item_update_scheduler.js?v=39.00.00" defer></script>
|
||||
<script src="js/simulation_runtime_helpers.js?v=39.00.00" defer></script>
|
||||
<script src="js/tarinai_update_policy.js?v=39.00.00" defer></script>
|
||||
<script src="js/simulation_environment_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/simulation_item_ant_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/simulation_effects_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/simulation_creature_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/simulation_maintenance_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/simulation_ambient_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/simulation_systems.js?v=39.00.00" defer></script>
|
||||
<script src="js/world_update_phases.js?v=39.00.00" defer></script>
|
||||
<script src="js/system_order.js?v=39.00.00" defer></script>
|
||||
<script src="js/simulation.js?v=39.00.00" defer></script>
|
||||
<script src="js/world_update.js?v=39.00.00" defer></script>
|
||||
<script src="js/world_tool_actions.js?v=39.00.00" defer></script>
|
||||
<script src="js/world_placement_log.js?v=39.00.00" defer></script>
|
||||
<script src="js/world_event_effects.js?v=39.00.00" defer></script>
|
||||
<script src="js/command_dispatcher.js?v=39.00.00" defer></script>
|
||||
<script src="js/text_catalog.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_log.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_helpers.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_selected.js?v=39.00.00" defer></script>
|
||||
<script src="js/save_schema.js?v=39.00.00" defer></script>
|
||||
<script src="js/snapshot_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/restore_coordinator.js?v=39.00.00" defer></script>
|
||||
<script src="js/history_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/save_codec.js?v=39.00.00" defer></script>
|
||||
<script src="js/save_storage.js?v=39.00.00" defer></script>
|
||||
<script src="js/save_system.js?v=39.00.00" defer></script>
|
||||
<script src="js/patch_helpers.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_tooltips.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_layout_dialogs.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_ground.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_tools.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_input_shared.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_input_touch.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_input_mouse.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_bind.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_charts.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_family_data.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_family_async.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_family_layout.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_family_paths.js?v=39.00.00" defer></script>
|
||||
<script src="js/ui_family_render.js?v=39.00.00" defer></script>
|
||||
<script src="js/main.js?v=39.00.00" defer></script>
|
||||
<script src="js/debug_tools.js?v=39.00.00" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -30,22 +30,129 @@
|
|||
|
||||
function resolveEndpointObject(endpoint, worldRef) {
|
||||
if (!endpoint || !worldRef) return null;
|
||||
const allowFuzzy = endpoint.fuzzyResolve === true || endpoint.legacyFuzzy === true;
|
||||
if (endpoint.kind === "tarinai") {
|
||||
let found = (worldRef.tarinai || []).find(t => t && !t.dead && t.id === endpoint.id);
|
||||
if (!found && Number.isFinite(endpoint.x) && Number.isFinite(endpoint.y)) {
|
||||
if (!found && allowFuzzy && Number.isFinite(endpoint.x) && Number.isFinite(endpoint.y)) {
|
||||
found = (worldRef.tarinai || []).find(t => t && !t.dead && distXY(t.x, t.y, endpoint.x, endpoint.y) <= Math.max(40, (t.radius || 20) * 1.6));
|
||||
if (found) endpoint.id = found.id;
|
||||
if (found) {
|
||||
endpoint.id = found.id;
|
||||
endpoint.fuzzyResolve = false;
|
||||
endpoint.legacyFuzzy = false;
|
||||
}
|
||||
}
|
||||
return found || null;
|
||||
}
|
||||
let found = (worldRef.items || []).find(it => it && !it.dead && it.id === endpoint.id);
|
||||
if (!found && Number.isFinite(endpoint.x) && Number.isFinite(endpoint.y)) {
|
||||
if (!found && allowFuzzy && Number.isFinite(endpoint.x) && Number.isFinite(endpoint.y)) {
|
||||
found = (worldRef.items || []).find(it => it && !it.dead && it.type === endpoint.type && distXY(it.x, it.y, endpoint.x, endpoint.y) <= Math.max(44, (it.r || 20) * 1.8));
|
||||
if (found) endpoint.id = found.id;
|
||||
if (found) {
|
||||
endpoint.id = found.id;
|
||||
endpoint.fuzzyResolve = false;
|
||||
endpoint.legacyFuzzy = false;
|
||||
}
|
||||
}
|
||||
return found || null;
|
||||
}
|
||||
|
||||
function itemAngle(item) {
|
||||
return typeof itemAngleFor === "function" ? itemAngleFor(item) : (Number(item?.angle) || 0);
|
||||
}
|
||||
|
||||
function isMechanicalLinkTarget(item) {
|
||||
return Boolean(item && !item.dead && global.TarinaiMechanicalSystem?.isMechanicalType?.(item.type));
|
||||
}
|
||||
|
||||
function localToWorld(item, lx, ly) {
|
||||
const a = itemAngle(item);
|
||||
const c = Math.cos(a), s = Math.sin(a);
|
||||
return {
|
||||
x: (Number(item?.x || 0) || 0) + lx * c - ly * s,
|
||||
y: (Number(item?.y || 0) || 0) + lx * s + ly * c,
|
||||
};
|
||||
}
|
||||
|
||||
function worldToLocal(item, x, y) {
|
||||
const a = itemAngle(item);
|
||||
const dx = (Number(x || 0) || 0) - (Number(item?.x || 0) || 0);
|
||||
const dy = (Number(y || 0) || 0) - (Number(item?.y || 0) || 0);
|
||||
const c = Math.cos(-a), s = Math.sin(-a);
|
||||
return { x: dx * c - dy * s, y: dx * s + dy * c };
|
||||
}
|
||||
|
||||
function nearestMechanicalLocalPoint(item, lx, ly) {
|
||||
if (!isMechanicalLinkTarget(item)) return null;
|
||||
const segments = global.TarinaiMechanicalSystem?.sanitizeSegments?.(item) || [];
|
||||
let best = null;
|
||||
for (const seg of segments) {
|
||||
if (!Array.isArray(seg) || seg.length < 4) continue;
|
||||
const x1 = Number(seg[0]) || 0, y1 = Number(seg[1]) || 0;
|
||||
const x2 = Number(seg[2]) || 0, y2 = Number(seg[3]) || 0;
|
||||
const vx = x2 - x1, vy = y2 - y1;
|
||||
const len2 = vx * vx + vy * vy;
|
||||
if (len2 < 16) continue;
|
||||
const t = clamp(((lx - x1) * vx + (ly - y1) * vy) / len2, 0, 1);
|
||||
const x = x1 + vx * t;
|
||||
const y = y1 + vy * t;
|
||||
const d = Math.hypot(lx - x, ly - y);
|
||||
if (!best || d < best.d) best = { x, y, d };
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
function snapEndpointToTarget(endpoint, worldRef) {
|
||||
const obj = resolveEndpointObject(endpoint, worldRef);
|
||||
if (!endpoint || !isMechanicalLinkTarget(obj)) return endpoint;
|
||||
let local;
|
||||
if (!endpoint.center && (Number.isFinite(Number(endpoint.localX)) || Number.isFinite(Number(endpoint.localY)))) {
|
||||
local = { x: Number(endpoint.localX || 0) || 0, y: Number(endpoint.localY || 0) || 0 };
|
||||
} else if (Number.isFinite(Number(endpoint.x)) && Number.isFinite(Number(endpoint.y))) {
|
||||
local = worldToLocal(obj, endpoint.x, endpoint.y);
|
||||
} else {
|
||||
local = { x: 0, y: 0 };
|
||||
}
|
||||
const snapped = nearestMechanicalLocalPoint(obj, local.x, local.y);
|
||||
if (!snapped) return endpoint;
|
||||
const world = localToWorld(obj, snapped.x, snapped.y);
|
||||
endpoint.localX = snapped.x;
|
||||
endpoint.localY = snapped.y;
|
||||
endpoint.x = world.x;
|
||||
endpoint.y = world.y;
|
||||
endpoint.center = false;
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
function remapLinksForEditedMechanicalItem(worldRef, target, reason = "mechanical-shape-edited") {
|
||||
if (!worldRef || !isMechanicalLinkTarget(target)) return 0;
|
||||
let changed = 0;
|
||||
const remap = (endpoint) => {
|
||||
if (!endpoint || endpoint.kind !== "item" || endpoint.id !== target.id) return false;
|
||||
const beforeX = Number(endpoint.localX || 0) || 0;
|
||||
const beforeY = Number(endpoint.localY || 0) || 0;
|
||||
const beforeWorldX = Number(endpoint.x || 0) || 0;
|
||||
const beforeWorldY = Number(endpoint.y || 0) || 0;
|
||||
snapEndpointToTarget(endpoint, worldRef);
|
||||
const localDelta = Math.hypot((Number(endpoint.localX || 0) || 0) - beforeX, (Number(endpoint.localY || 0) || 0) - beforeY);
|
||||
const worldDelta = Math.hypot((Number(endpoint.x || 0) || 0) - beforeWorldX, (Number(endpoint.y || 0) || 0) - beforeWorldY);
|
||||
return localDelta > 0.001 || worldDelta > 0.001;
|
||||
};
|
||||
for (const item of worldRef.items || []) {
|
||||
if (!item || item.dead || (item.type !== "rope" && item.type !== "rod")) continue;
|
||||
const a = remap(item.linkA);
|
||||
const b = remap(item.linkB);
|
||||
if (a || b) {
|
||||
item.world = worldRef;
|
||||
changed += 1;
|
||||
}
|
||||
}
|
||||
if (remap(worldRef.pendingLinkEndpoint)) changed += 1;
|
||||
if (changed) {
|
||||
worldRef.drawListDirty = true;
|
||||
worldRef.markSpatialDirty?.(reason);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
function endpointWorld(endpoint, worldRef, depth = 0, seen = null) {
|
||||
const obj = resolveEndpointObject(endpoint, worldRef);
|
||||
if (obj && (obj.type === "rope" || obj.type === "rod") && worldRef) obj.world = worldRef;
|
||||
|
|
@ -66,7 +173,7 @@
|
|||
const lx = Number(endpoint.localX || 0) || 0;
|
||||
const ly = Number(endpoint.localY || 0) || 0;
|
||||
if (endpoint.center || (!lx && !ly)) return { x: obj.x || 0, y: obj.y || 0, obj };
|
||||
const a = typeof itemAngleFor === "function" ? itemAngleFor(obj) : (Number(obj.angle) || 0);
|
||||
const a = itemAngle(obj);
|
||||
const c = Math.cos(a), s = Math.sin(a);
|
||||
return { x: (obj.x || 0) + lx * c - ly * s, y: (obj.y || 0) + lx * s + ly * c, obj };
|
||||
}
|
||||
|
|
@ -283,6 +390,8 @@
|
|||
resolveEndpointObject,
|
||||
endpointMass,
|
||||
moveEndpointObject,
|
||||
snapEndpointToTarget,
|
||||
remapLinksForEditedMechanicalItem,
|
||||
updateFlexibleLink,
|
||||
updateRigidLink,
|
||||
updateLink,
|
||||
|
|
@ -290,5 +399,5 @@
|
|||
});
|
||||
|
||||
global.TarinaiConstraintSystem = api;
|
||||
global.TarinaiLinkRuntime = Object.freeze({ endpointWorld, pointSegmentDistance });
|
||||
global.TarinaiLinkRuntime = Object.freeze({ endpointWorld, pointSegmentDistance, snapEndpointToTarget, remapLinksForEditedMechanicalItem });
|
||||
})(typeof window !== "undefined" ? window : globalThis);
|
||||
|
|
|
|||
29
js/render.js
29
js/render.js
|
|
@ -258,10 +258,23 @@ function drawOperationToolPreview(ctx, world) {
|
|||
const type = world.copyBuffer.type || "";
|
||||
const item = world.copyPreviewItemAt?.(p.x, p.y);
|
||||
if (item) {
|
||||
const pad = typeof CONFIG !== "undefined" ? (CONFIG.worldPadding ?? 0) : 0;
|
||||
const rectOutside = (rect) => Boolean(rect && (rect.left < pad || rect.top < pad || rect.right > world.w - pad || rect.bottom > world.h - pad));
|
||||
const circleOutside = (cx, cy, radius) => cx - radius < pad || cy - radius < pad || cx + radius > world.w - pad || cy + radius > world.h - pad;
|
||||
const previewRects = world.solidObstacleRects?.(item) || [];
|
||||
const boundsBlocked = previewRects.length
|
||||
? previewRects.some(rr => rectOutside(rr.oriented ? {
|
||||
left: (rr.cx || p.x) - (rr.halfW || 10) - (rr.halfH || 5),
|
||||
right: (rr.cx || p.x) + (rr.halfW || 10) + (rr.halfH || 5),
|
||||
top: (rr.cy || p.y) - (rr.halfW || 10) - (rr.halfH || 5),
|
||||
bottom: (rr.cy || p.y) + (rr.halfW || 10) + (rr.halfH || 5),
|
||||
} : rr))
|
||||
: circleOutside(p.x, p.y, Math.max(14, (item.r || itemRadiusFor?.(type, 16) || 16) * 1.25));
|
||||
const blocked = boundsBlocked || Boolean(world.placementBlocked?.(item) || world.fencePlacementBlocked?.(item));
|
||||
let copyPreviewDrew = false;
|
||||
if (typeof item.draw === "function") {
|
||||
ctx.save();
|
||||
ctx.globalAlpha = 0.74;
|
||||
ctx.globalAlpha = blocked ? 0.44 : 0.74;
|
||||
try { item.draw(ctx, world.time || 0, typeof getLightingState === "function" ? getLightingState(world) : null); copyPreviewDrew = true; } catch (_) { copyPreviewDrew = false; }
|
||||
ctx.restore();
|
||||
}
|
||||
|
|
@ -273,18 +286,18 @@ function drawOperationToolPreview(ctx, world) {
|
|||
const bctx = buffer.getContext("2d");
|
||||
if (bctx && globalThis.drawToolItemPreview(bctx, type, { width: buffer.width, height: buffer.height, compact: true }) !== false) {
|
||||
ctx.save();
|
||||
ctx.globalAlpha = 0.74;
|
||||
ctx.globalAlpha = blocked ? 0.44 : 0.74;
|
||||
ctx.drawImage(buffer, p.x - previewSize / 2, p.y - previewSize / 2, previewSize, previewSize);
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
ctx.save();
|
||||
ctx.globalAlpha = 0.50;
|
||||
ctx.setLineDash([7, 5]);
|
||||
ctx.lineWidth = 2;
|
||||
ctx.strokeStyle = "rgba(128,92,198,0.86)";
|
||||
ctx.fillStyle = "rgba(150,110,220,0.12)";
|
||||
const rects = world.solidObstacleRects?.(item) || [];
|
||||
ctx.globalAlpha = blocked ? 0.58 : 0.50;
|
||||
ctx.setLineDash(blocked ? [5, 4] : [7, 5]);
|
||||
ctx.lineWidth = blocked ? 2.2 : 2;
|
||||
ctx.strokeStyle = blocked ? "rgba(194,70,58,0.88)" : "rgba(110,178,55,0.88)";
|
||||
ctx.fillStyle = blocked ? "rgba(232,84,72,0.14)" : "rgba(190,236,92,0.15)";
|
||||
const rects = previewRects;
|
||||
if (rects.length) {
|
||||
for (const rr of rects) {
|
||||
if (rr.oriented) {
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@
|
|||
if (typeof t.refreshEffectiveSize === "function") t.refreshEffectiveSize();
|
||||
return t;
|
||||
}
|
||||
function itemExtra(item, tarinaiIndex = new Map()) {
|
||||
function itemExtra(item, tarinaiIndex = new Map(), itemIndex = new Map()) {
|
||||
const type = item?.type || "";
|
||||
if (item?.isStructure) {
|
||||
const owner = tarinaiIndex.get(item.ownerId) ?? -1;
|
||||
|
|
@ -346,7 +346,24 @@
|
|||
];
|
||||
|
||||
if (type === "rope" || type === "rod") {
|
||||
const cloneEndpoint = ep => ep ? { kind: ep.kind || "item", id: ep.id || "", type: ep.type || "", label: ep.label || "", localX: q(ep.localX || 0, 1), localY: q(ep.localY || 0, 1), center: ep.center ? 1 : 0, x: q(ep.x || 0, 1), y: q(ep.y || 0, 1), attachT: Number.isFinite(Number(ep.attachT)) ? q(ep.attachT, 1000) : null } : null;
|
||||
const cloneEndpoint = ep => {
|
||||
if (!ep) return null;
|
||||
const kind = ep.kind || "item";
|
||||
const refIdx = kind === "tarinai" ? (tarinaiIndex.get(ep.id) ?? -1) : (itemIndex.get(ep.id) ?? -1);
|
||||
return {
|
||||
kind,
|
||||
id: ep.id || "",
|
||||
refIdx,
|
||||
type: ep.type || "",
|
||||
label: ep.label || "",
|
||||
localX: q(ep.localX || 0, 1),
|
||||
localY: q(ep.localY || 0, 1),
|
||||
center: ep.center ? 1 : 0,
|
||||
x: q(ep.x || 0, 1),
|
||||
y: q(ep.y || 0, 1),
|
||||
attachT: Number.isFinite(Number(ep.attachT)) ? q(ep.attachT, 1000) : null,
|
||||
};
|
||||
};
|
||||
return [cloneEndpoint(item.linkA), cloneEndpoint(item.linkB), q(item.linkLength || item.r * 2 || 80, 1), q(item.linkMidX || item.x || 0, 1), q(item.linkMidY || item.y || 0, 1), q(item.linkMidVX || 0, 10), q(item.linkMidVY || 0, 10)];
|
||||
}
|
||||
if (type === "duplicator") return [enumIndex(ITEM_TYPE_IDS, item.storedFoodType || "", -1)];
|
||||
|
|
@ -359,12 +376,12 @@
|
|||
if (typeof global.isServingFoodType === "function" && global.isServingFoodType(type)) return [q(item.foodServingsRemaining ?? item.amount, 10), q(item.foodServingsMax, 10)];
|
||||
return [];
|
||||
}
|
||||
function compactItem(item, index, tarinaiIndex = new Map()) {
|
||||
function compactItem(item, index, tarinaiIndex = new Map(), itemIndex = new Map()) {
|
||||
const typeId = enumIndex(ITEM_TYPE_IDS, item?.type || "", -1);
|
||||
if (typeId < 0 || item?.type === "trace") return null;
|
||||
return [typeId, q(item?.x, 1), q(item?.y, 1), q(item?.amount ?? item?.hp, 10), itemExtra(item, tarinaiIndex)];
|
||||
return [typeId, q(item?.x, 1), q(item?.y, 1), q(item?.amount ?? item?.hp, 10), itemExtra(item, tarinaiIndex, itemIndex)];
|
||||
}
|
||||
function applyItemExtra(item, extra, tarinaiList = []) {
|
||||
function applyItemExtra(item, extra, tarinaiList = [], itemList = []) {
|
||||
if (!Array.isArray(extra)) return;
|
||||
const type = item.type || "";
|
||||
if (item.isStructure) {
|
||||
|
|
@ -426,7 +443,27 @@
|
|||
item.r = Math.max(item.r || 64, Math.min(460, extent));
|
||||
} else if (type === "rope" || type === "rod") {
|
||||
const e = Array.isArray(extra) ? extra : [];
|
||||
const normalizeEndpoint = ep => ep ? { kind: ep.kind || "item", id: ep.id || "", type: ep.type || "", label: ep.label || "", localX: u(ep.localX, 1, 0), localY: u(ep.localY, 1, 0), center: !!ep.center, x: u(ep.x, 1, item.x || 0), y: u(ep.y, 1, item.y || 0), attachT: ep.attachT == null ? null : clamp(u(ep.attachT, 1000, 0.5), 0, 1) } : null;
|
||||
const normalizeEndpoint = ep => {
|
||||
if (!ep) return null;
|
||||
const kind = ep.kind || "item";
|
||||
const refIdx = Number(ep.refIdx);
|
||||
const indexedTarget = Number.isInteger(refIdx) && refIdx >= 0
|
||||
? (kind === "tarinai" ? tarinaiList[refIdx] : itemList[refIdx])
|
||||
: null;
|
||||
return {
|
||||
kind,
|
||||
id: indexedTarget?.id || ep.id || "",
|
||||
type: ep.type || indexedTarget?.type || "",
|
||||
label: ep.label || indexedTarget?.name || "",
|
||||
localX: u(ep.localX, 1, 0),
|
||||
localY: u(ep.localY, 1, 0),
|
||||
center: !!ep.center,
|
||||
x: u(ep.x, 1, item.x || 0),
|
||||
y: u(ep.y, 1, item.y || 0),
|
||||
attachT: ep.attachT == null ? null : clamp(u(ep.attachT, 1000, 0.5), 0, 1),
|
||||
fuzzyResolve: !indexedTarget && !Number.isInteger(refIdx),
|
||||
};
|
||||
};
|
||||
item.linkA = normalizeEndpoint(e[0]);
|
||||
item.linkB = normalizeEndpoint(e[1]);
|
||||
item.linkLength = Math.max(24, u(e[2], 1, item.linkLength || 80));
|
||||
|
|
@ -467,13 +504,13 @@
|
|||
const itemRecords = [];
|
||||
for (const it of (worldRef.items || [])) {
|
||||
if (!it || it.dead || it.type === "trace" || enumIndex(ITEM_TYPE_IDS, it.type || "", -1) < 0) continue;
|
||||
const row = compactItem(it, itemRecords.length, tarinaiIndex);
|
||||
if (row) itemRecords.push({ item: it, row });
|
||||
const typeId = enumIndex(ITEM_TYPE_IDS, it.type || "", -1);
|
||||
itemRecords.push({ item: it, sortTypeId: typeId, sortX: q(it.x, 1), sortY: q(it.y, 1) });
|
||||
}
|
||||
itemRecords.sort((a, b) => (a.row[0] || 0) - (b.row[0] || 0) || mortonKeyXY(a.row[1], a.row[2]) - mortonKeyXY(b.row[1], b.row[2]) || String(a.item?.id || "").localeCompare(String(b.item?.id || "")));
|
||||
itemRecords.sort((a, b) => (a.sortTypeId || 0) - (b.sortTypeId || 0) || mortonKeyXY(a.sortX, a.sortY) - mortonKeyXY(b.sortX, b.sortY) || String(a.item?.id || "").localeCompare(String(b.item?.id || "")));
|
||||
const itemIndex = new Map();
|
||||
itemRecords.forEach((rec, i) => { if (rec.item?.id) itemIndex.set(rec.item.id, i); });
|
||||
const itemRows = itemRecords.map(rec => rec.row);
|
||||
const itemRows = itemRecords.map((rec, i) => compactItem(rec.item, i, tarinaiIndex, itemIndex)).filter(Boolean);
|
||||
return {
|
||||
v: SNAPSHOT_VERSION,
|
||||
a: "tj1",
|
||||
|
|
@ -535,9 +572,13 @@
|
|||
item.id = `li${idx}`;
|
||||
item.world = worldRef;
|
||||
item.amount = u(row[3], 10, item.amount || 1);
|
||||
applyItemExtra(item, extra, worldRef.tarinai);
|
||||
item.__savedExtra = extra;
|
||||
worldRef.items.push(item);
|
||||
}
|
||||
for (const item of worldRef.items) {
|
||||
applyItemExtra(item, item.__savedExtra || [], worldRef.tarinai, worldRef.items);
|
||||
delete item.__savedExtra;
|
||||
}
|
||||
for (const t of worldRef.tarinai) {
|
||||
if (Number.isInteger(t.__savedPinIdx) && t.__savedPinIdx >= 0) t.stuckPushpinId = worldRef.items[t.__savedPinIdx]?.id || null;
|
||||
if (Number.isInteger(t.__savedNestIdx) && t.__savedNestIdx >= 0) t.insideNestBoxId = worldRef.items[t.__savedNestIdx]?.id || null;
|
||||
|
|
|
|||
|
|
@ -125,9 +125,15 @@ function resizeFieldFromWheel(e) {
|
|||
}
|
||||
|
||||
function selectTool(tool) {
|
||||
const wasCopyArmed = world.tool === "copy" && tool === "copy" && Boolean(world.copyBuffer);
|
||||
const result = window.TarinaiCommands?.dispatch?.(world, { type: "tool.select", toolId: tool });
|
||||
const activeTool = result?.toolId || world.tool || tool;
|
||||
if (activeTool !== "rope" && activeTool !== "rod") world.pendingLinkEndpoint = null;
|
||||
if (activeTool !== "copy") world.copyBuffer = null;
|
||||
else if (wasCopyArmed) {
|
||||
world.copyBuffer = null;
|
||||
showToast("\u30b3\u30d4\u30fc\u3092\u89e3\u9664\u3057\u307e\u3057\u305f\u3002");
|
||||
}
|
||||
for (const btn of uiCache.toolButtons) {
|
||||
btn.classList.toggle("selected", btn.dataset.tool === activeTool);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
(function () {
|
||||
const APP_VERSION = "38.00.00";
|
||||
const APP_VERSION = "39.00.00";
|
||||
const APP_BUILD = "lab-ground-wash-and-freezer-removal-v38";
|
||||
const APP_CACHE_NAME = `tarinai-colony-${APP_VERSION}`;
|
||||
const STATIC_VERSION_PARAM = `v=${APP_VERSION}`;
|
||||
|
|
|
|||
|
|
@ -392,6 +392,7 @@
|
|||
const extent = worldRef?.rotatorExtent?.(item);
|
||||
if (Number.isFinite(extent)) item.r = Math.max(32, Math.min(460, extent));
|
||||
item.rotatorEditorOpenAt = worldRef?.time || 0;
|
||||
global.TarinaiLinkRuntime?.remapLinksForEditedMechanicalItem?.(worldRef, item, "rotator-link-remap");
|
||||
worldRef?.markSpatialDirty?.("rotator-edited");
|
||||
worldRef.drawListDirty = true;
|
||||
worldRef?.log?.("回転体の設計を変更した。", "observe");
|
||||
|
|
@ -672,6 +673,7 @@
|
|||
item.reciprocatorAnchorY = item.y - Math.sin(sa) * halfTravel * (Number(item.reciprocatorPhase || 0) || 0);
|
||||
const extent = worldRef?.rotatorExtent?.(item);
|
||||
if (Number.isFinite(extent)) item.r = Math.max(32, Math.min(460, extent));
|
||||
global.TarinaiLinkRuntime?.remapLinksForEditedMechanicalItem?.(worldRef, item, "reciprocator-link-remap");
|
||||
worldRef?.markSpatialDirty?.("reciprocator-edited");
|
||||
worldRef.drawListDirty = true;
|
||||
worldRef?.log?.("往復体の設計を変更した。", "observe");
|
||||
|
|
@ -687,11 +689,47 @@
|
|||
return true;
|
||||
}
|
||||
|
||||
function copyTargetAt(worldRef, x, y) {
|
||||
let blockedReason = "";
|
||||
const collision = global.TarinaiCollisionFootprints;
|
||||
const items = worldRef?.items || [];
|
||||
for (let i = items.length - 1; i >= 0; i--) {
|
||||
const it = items[i];
|
||||
if (!it || it.dead) continue;
|
||||
const type = String(it.type || "");
|
||||
if (type === "trace" || type === "splat" || type === "ant_corpse") continue;
|
||||
if (type === "rope" || type === "rod") {
|
||||
const runtime = global.TarinaiLinkRuntime;
|
||||
const a = runtime?.endpointWorld?.(it.linkA, worldRef);
|
||||
const b = runtime?.endpointWorld?.(it.linkB, worldRef);
|
||||
const d = runtime?.pointSegmentDistance?.(x, y, a?.x ?? it.x, a?.y ?? it.y, b?.x ?? it.x, b?.y ?? it.y) ?? Infinity;
|
||||
const tolerance = worldRef?.screenSizeToWorld ? worldRef.screenSizeToWorld(12) : 12;
|
||||
if (d <= tolerance && !blockedReason) blockedReason = "link";
|
||||
continue;
|
||||
}
|
||||
if (typeof isPinType === "function" && isPinType(type) && it.pinState === "lodged") {
|
||||
const d = distXY(x, y, it.x, it.y);
|
||||
if (d <= Math.max(24, (it.r || 12) * 1.8) && !blockedReason) blockedReason = "lodged_pin";
|
||||
continue;
|
||||
}
|
||||
const d = distXY(x, y, it.x, it.y);
|
||||
let result = null;
|
||||
if (collision?.hitTestItem) {
|
||||
const isPrecise = Boolean(global.TarinaiMechanicalSystem?.isMechanicalType?.(type) || worldRef?.isFenceType?.(type) || type === "nest_box");
|
||||
result = collision.hitTestItem(worldRef, it, x, y, {
|
||||
padding: isPrecise ? 10 : 4,
|
||||
radiusMultiplier: isPrecise ? 1.12 : 1.18,
|
||||
});
|
||||
}
|
||||
const hit = result ? Boolean(result.hit) : d <= Math.max(16, (it.r || 16) * 1.18);
|
||||
if (!hit) continue;
|
||||
return { item: it, reason: "" };
|
||||
}
|
||||
return { item: null, reason: blockedReason };
|
||||
}
|
||||
|
||||
function copyableItemAt(worldRef, x, y) {
|
||||
const it = worldRef?.findDeleteToolTargetAt?.(x, y);
|
||||
if (!it || it.dead || it.type === "trace" || it.type === "splat" || it.type === "ant_corpse") return null;
|
||||
if (typeof isPinType === "function" && isPinType(it.type) && it.pinState === "lodged") return null;
|
||||
return it;
|
||||
return copyTargetAt(worldRef, x, y).item;
|
||||
}
|
||||
|
||||
function makeCopyBufferForItem(item) {
|
||||
|
|
@ -704,17 +742,12 @@
|
|||
toolSize: item.toolSize || "medium",
|
||||
foodServingScale: Number(item.foodServingScale || 1) || 1,
|
||||
foodServingsMax: Number(item.foodServingsMax || 0) || 0,
|
||||
foodServingsRemaining: Number(item.foodServingsRemaining || 0) || 0,
|
||||
seed: Number.isFinite(Number(item.seed)) ? Number(item.seed) : null,
|
||||
spin: Number.isFinite(Number(item.spin)) ? Number(item.spin) : 0,
|
||||
zunchiVariant: item.zunchiVariant || "",
|
||||
stage: item.stage || "",
|
||||
freshness: Number.isFinite(Number(item.freshness)) ? Number(item.freshness) : null,
|
||||
fertility: Number.isFinite(Number(item.fertility)) ? Number(item.fertility) : null,
|
||||
grassStage: Number.isFinite(Number(item.grassStage)) ? Number(item.grassStage) : null,
|
||||
growth: Number.isFinite(Number(item.growth)) ? Number(item.growth) : null,
|
||||
health: Number.isFinite(Number(item.health)) ? Number(item.health) : null,
|
||||
fuseTimer: Number.isFinite(Number(item.fuseTimer)) ? Number(item.fuseTimer) : null,
|
||||
fuseMax: Number.isFinite(Number(item.fuseMax)) ? Number(item.fuseMax) : null,
|
||||
};
|
||||
if (item.type === "signboard") data.text = item.text || "";
|
||||
|
|
@ -747,9 +780,11 @@
|
|||
if (Number.isFinite(Number(data.spin))) item.spin = Number(data.spin);
|
||||
if (item.type === "zunchi") {
|
||||
if (data.zunchiVariant) item.zunchiVariant = String(data.zunchiVariant);
|
||||
if (data.stage) item.stage = String(data.stage);
|
||||
if (Number.isFinite(Number(data.freshness))) item.freshness = Number(data.freshness);
|
||||
if (Number.isFinite(Number(data.fertility))) item.fertility = Number(data.fertility);
|
||||
item.stage = "fresh";
|
||||
item.stageTimer = 0;
|
||||
item.freshness = 1;
|
||||
item.fertility = 0;
|
||||
item.spawnGrace = Math.max(Number(item.spawnGrace || 0) || 0, 10);
|
||||
}
|
||||
if (item.type === "grass") {
|
||||
if (Number.isFinite(Number(data.grassStage))) item.grassStage = Number(data.grassStage);
|
||||
|
|
@ -757,8 +792,8 @@
|
|||
if (Number.isFinite(Number(data.health))) item.health = Number(data.health);
|
||||
}
|
||||
if (item.type === "firecracker") {
|
||||
if (Number.isFinite(Number(data.fuseTimer))) item.fuseTimer = Number(data.fuseTimer);
|
||||
if (Number.isFinite(Number(data.fuseMax))) item.fuseMax = Number(data.fuseMax);
|
||||
item.fuseTimer = Math.max(0.1, Number(item.fuseMax || 5) || 5);
|
||||
}
|
||||
if (typeof isRotatableItemType === "function" && isRotatableItemType(item.type)) item.angle = Number(data.angle || 0) || 0;
|
||||
if (item.type === "signboard") item.text = String(data.text || "");
|
||||
|
|
@ -797,13 +832,23 @@
|
|||
item.toolSize = data.toolSize || item.toolSize || "medium";
|
||||
item.foodServingScale = Number(data.foodServingScale || item.foodServingScale || 1) || 1;
|
||||
item.foodServingsMax = Math.max(1, Number(data.foodServingsMax || item.foodServingsMax || item.amount || 1));
|
||||
item.foodServingsRemaining = Math.max(1, Number(data.foodServingsRemaining || item.foodServingsRemaining || item.amount || 1));
|
||||
item.foodServingsRemaining = item.foodServingsMax;
|
||||
item.amount = item.foodServingsRemaining;
|
||||
}
|
||||
if (Number.isFinite(Number(item.x))) item.prevX = item.x;
|
||||
if (Number.isFinite(Number(item.y))) item.prevY = item.y;
|
||||
item.vx = 0;
|
||||
item.vy = 0;
|
||||
item.spinVelocity = 0;
|
||||
if (typeof isPinType === "function" && isPinType(item.type)) {
|
||||
item.pinState = "loose";
|
||||
item.pinTargetId = "";
|
||||
item.vx = 0; item.vy = 0; item.spinVelocity = 0;
|
||||
item.pinAttachAngle = 0;
|
||||
item.pinAttachDistance = 0;
|
||||
item.pinOffsetY = 0;
|
||||
item.pinDamageTick = 0;
|
||||
item.pinFallCheckTimer = 0;
|
||||
item.pinLogAt = -999;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
|
@ -819,8 +864,14 @@
|
|||
for (let i = (worldRef?.items || []).length - 1; i >= 0; i--) {
|
||||
const it = worldRef.items[i];
|
||||
if (!isEditableItem(it)) continue;
|
||||
const d = distXY(x, y, it.x, it.y);
|
||||
if (d <= Math.max(54, (it.r || 24) * 2.4) && d < bestD) { best = it; bestD = d; }
|
||||
let d = distXY(x, y, it.x, it.y);
|
||||
let hit = d <= Math.max(30, (it.r || 24) * 1.35);
|
||||
if (global.TarinaiMechanicalSystem?.isMechanicalType?.(it.type) || worldRef?.isFenceType?.(it.type)) {
|
||||
const result = global.TarinaiCollisionFootprints?.hitTestItem?.(worldRef, it, x, y, { padding: 14, radiusMultiplier: 1.25 }) || { hit: false, distance: d };
|
||||
hit = Boolean(result.hit);
|
||||
d = Math.min(d, result.distance ?? d);
|
||||
}
|
||||
if (hit && d < bestD) { best = it; bestD = d; }
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
|
@ -885,9 +936,82 @@
|
|||
return true;
|
||||
}
|
||||
|
||||
function isPhysicsObstacleItemType(type = "") {
|
||||
const key = String(type || "");
|
||||
return Boolean(
|
||||
key === "rope" || key === "rod"
|
||||
|| global.TarinaiMechanicalSystem?.isMechanicalType?.(key)
|
||||
|| (typeof isFenceItemType === "function" && isFenceItemType(key))
|
||||
);
|
||||
}
|
||||
|
||||
function isSoftPhysicsIgnoredItemType(type = "") {
|
||||
const key = String(type || "");
|
||||
return key === "water" || key === "grass_bed";
|
||||
}
|
||||
|
||||
function softItemRadius(item) {
|
||||
if (!item) return 12;
|
||||
return Math.max(8, Number(item.r || item.radius || itemRadiusFor?.(item.type, 12) || 12) || 12);
|
||||
}
|
||||
|
||||
function physicsItemOverlapsSoftItem(worldRef, physicsItem, softItem) {
|
||||
if (!worldRef || !physicsItem || !softItem || softItem.dead) return false;
|
||||
const r = softItemRadius(softItem);
|
||||
if (physicsItem.type === "rope" || physicsItem.type === "rod") {
|
||||
const runtime = global.TarinaiLinkRuntime;
|
||||
const a = runtime?.endpointWorld?.(physicsItem.linkA, worldRef);
|
||||
const b = runtime?.endpointWorld?.(physicsItem.linkB, worldRef);
|
||||
if (a && b) {
|
||||
const d = runtime?.pointSegmentDistance?.(softItem.x, softItem.y, a.x, a.y, b.x, b.y);
|
||||
return Number.isFinite(d) && d <= r + (physicsItem.type === "rod" ? 9 : 7);
|
||||
}
|
||||
}
|
||||
const rects = worldRef.solidObstacleRects?.(physicsItem) || [];
|
||||
if (rects.length) {
|
||||
return rects.some(rect => global.TarinaiCollisionFootprints?.rectCircleOverlap?.(rect, softItem.x, softItem.y, r, 0.5));
|
||||
}
|
||||
const pr = Math.max(10, Number(physicsItem.r || physicsItem.radius || itemRadiusFor?.(physicsItem.type, 12) || 12) || 12);
|
||||
return distXY(physicsItem.x, physicsItem.y, softItem.x, softItem.y) <= pr + r;
|
||||
}
|
||||
|
||||
function clearSoftItemsUnderPhysicsItem(worldRef, item, reason = "physics-overlap-clear") {
|
||||
if (!worldRef || !item || !isPhysicsObstacleItemType(item.type)) return 0;
|
||||
let search = Math.max(80, Number(item.r || item.radius || 36) + 90);
|
||||
if (global.TarinaiMechanicalSystem?.isMechanicalType?.(item.type)) {
|
||||
search = Math.max(search, (global.TarinaiMechanicalSystem?.reach?.(item) || item.r || 80) + 96);
|
||||
} else if (item.type === "rope" || item.type === "rod") {
|
||||
search = Math.max(search, Number(item.linkLength || (item.r || 40) * 2 || 80) * 0.55 + 96);
|
||||
}
|
||||
let removed = 0;
|
||||
for (const soft of worldRef.nearbyItems?.(item.x, item.y, search, true) || worldRef.items || []) {
|
||||
if (!soft || soft === item || soft.dead || !isSoftPhysicsIgnoredItemType(soft.type)) continue;
|
||||
if (!physicsItemOverlapsSoftItem(worldRef, item, soft)) continue;
|
||||
const ok = global.TarinaiStructureLifecycle?.deleteItem?.(worldRef, soft, {
|
||||
reason,
|
||||
userReason: "物理アイテムに重なった",
|
||||
wake: true,
|
||||
});
|
||||
if (ok) removed += 1;
|
||||
}
|
||||
if (removed) {
|
||||
worldRef.markItemBucketsDirty?.(reason);
|
||||
worldRef.markSpatialDirty?.(reason);
|
||||
worldRef.drawListDirty = true;
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
global.TarinaiPhysicsSoftClear = Object.freeze({
|
||||
isPhysicsType: isPhysicsObstacleItemType,
|
||||
isSoftType: isSoftPhysicsIgnoredItemType,
|
||||
overlaps: physicsItemOverlapsSoftItem,
|
||||
clearForItem: clearSoftItemsUnderPhysicsItem,
|
||||
});
|
||||
|
||||
function clearOverlappingGrassBedsForPlacement(worldRef, item) {
|
||||
if (!worldRef || !item || item.type === "grass_bed" || item.type === "trace" || item.type === "splat") return 0;
|
||||
if (global.TarinaiMechanicalSystem?.isMechanicalType?.(item.type) || item.type === "rope" || item.type === "rod" || (typeof isFenceItemType === "function" && isFenceItemType(item.type))) return 0;
|
||||
if (isPhysicsObstacleItemType(item.type)) return clearSoftItemsUnderPhysicsItem(worldRef, item, "physics-placement-soft-clear");
|
||||
const radius = Math.max(16, item.r || item.radius || 12);
|
||||
let removed = 0;
|
||||
for (const bed of worldRef.nearbyItems?.(item.x, item.y, radius + 72) || worldRef.items || []) {
|
||||
|
|
@ -944,11 +1068,17 @@
|
|||
|
||||
useCopyToolAt(x, y) {
|
||||
if (!this.copyBuffer) {
|
||||
const target = copyableItemAt(this, x, y);
|
||||
if (!target) { showToast("コピーできるものがありません。"); return true; }
|
||||
const targetInfo = copyTargetAt(this, x, y);
|
||||
const target = targetInfo.item;
|
||||
if (!target) {
|
||||
if (targetInfo.reason === "link") showToast("\u30ed\u30fc\u30d7\u3068\u68d2\u306f\u30b3\u30d4\u30fc\u3067\u304d\u307e\u305b\u3093\u3002");
|
||||
else if (targetInfo.reason === "lodged_pin") showToast("\u523a\u3055\u3063\u305f\u30d4\u30f3\u306f\u30b3\u30d4\u30fc\u3067\u304d\u307e\u305b\u3093\u3002");
|
||||
else showToast("\u30b3\u30d4\u30fc\u3067\u304d\u308b\u3082\u306e\u304c\u3042\u308a\u307e\u305b\u3093\u3002");
|
||||
return true;
|
||||
}
|
||||
this.copyBuffer = makeCopyBufferForItem(target);
|
||||
showToast(`${toolLabel(target.type)}をコピーしました。`);
|
||||
this.log?.(`${toolLabel(target.type)}をコピーした。`, "observe");
|
||||
showToast(`${toolLabel(target.type)}\u3092\u30b3\u30d4\u30fc\u3057\u307e\u3057\u305f\u3002`);
|
||||
this.log?.(`${toolLabel(target.type)}\u3092\u30b3\u30d4\u30fc\u3057\u305f\u3002`, "observe");
|
||||
return true;
|
||||
}
|
||||
const item = this.copyPreviewItemAt?.(x, y);
|
||||
|
|
@ -960,17 +1090,12 @@
|
|||
if (placed.type === "grass" || placed.type === "trace" || placed.type === "splat") this.markTerrainDirtyAt?.(placed.x, placed.y, Math.max(placed.r || 24, 36), "copy-paste");
|
||||
forceImmediateToolVisualRefresh(this, "copy-paste");
|
||||
const label = toolLabel(item.type);
|
||||
this.log?.(`${label}を貼り付けた。`, "observe");
|
||||
showToast(`${label}を貼り付けました。`);
|
||||
this.log?.(`${label}\u3092\u8cbc\u308a\u4ed8\u3051\u305f\u3002`, "observe");
|
||||
showToast(`${label}\u3092\u8cbc\u308a\u4ed8\u3051\u307e\u3057\u305f\u3002`);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const target = copyableItemAt(this, x, y);
|
||||
if (target) {
|
||||
this.copyBuffer = makeCopyBufferForItem(target);
|
||||
showToast(`${toolLabel(target.type)}をコピーしました。`);
|
||||
this.log?.(`${toolLabel(target.type)}をコピーした。`, "observe");
|
||||
}
|
||||
showToast("\u305d\u3053\u306b\u306f\u8cbc\u308a\u4ed8\u3051\u3067\u304d\u307e\u305b\u3093\u3002");
|
||||
return true;
|
||||
},
|
||||
|
||||
|
|
@ -1158,6 +1283,7 @@
|
|||
if (item.type === "grass") showToast(`草はこのフィールドでは${this.grassLimit?.() ?? CONFIG.grassLimit ?? 99}本までです。`);
|
||||
return null;
|
||||
}
|
||||
clearSoftItemsUnderPhysicsItem(this, item, `place:${item.type}:soft-overlap-clear`);
|
||||
this.emit("tool:place", { item, type: item.type, dropped });
|
||||
this.emit("tool:placed", { item, type: item.type, dropped, tool: item.type });
|
||||
this.drawListDirty = true;
|
||||
|
|
|
|||
|
|
@ -178,6 +178,7 @@
|
|||
if (!hit || d >= bestD) continue;
|
||||
const local = this.linkPointLocalForItem?.(it, x, y, isMechanism || isFence) || { localX: 0, localY: 0 };
|
||||
best = { kind: "item", id: it.id, type: it.type, label: toolLabel(it.type), x: isMechanism || isFence ? x : it.x, y: isMechanism || isFence ? y : it.y, localX: local.localX, localY: local.localY, center: !(isMechanism || isFence) };
|
||||
if (isMechanism) global.TarinaiLinkRuntime?.snapEndpointToTarget?.(best, this);
|
||||
bestD = d;
|
||||
}
|
||||
return best;
|
||||
|
|
@ -195,6 +196,8 @@
|
|||
return true;
|
||||
}
|
||||
const first = this.pendingLinkEndpoint;
|
||||
global.TarinaiLinkRuntime?.snapEndpointToTarget?.(first, this);
|
||||
global.TarinaiLinkRuntime?.snapEndpointToTarget?.(endpoint, this);
|
||||
if (first.kind === endpoint.kind && first.id === endpoint.id && distXY(first.x, first.y, endpoint.x, endpoint.y) < 8) {
|
||||
showToast("別の位置または対象を選んでください。");
|
||||
return true;
|
||||
|
|
@ -217,6 +220,7 @@
|
|||
const placed = this.addItem?.(item, constraintType);
|
||||
this.pendingLinkEndpoint = null;
|
||||
if (!placed) { showToast(`${toolName}を追加できませんでした。`); return true; }
|
||||
global.TarinaiPhysicsSoftClear?.clearForItem?.(this, item, `${constraintType}-soft-overlap-clear`);
|
||||
forceImmediateToolVisualRefresh(this, `${constraintType}-create`);
|
||||
this.log?.(`${toolName}をつないだ。`, "observe");
|
||||
showToast(`${toolName}をつなぎました。`);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use strict";
|
||||
|
||||
const APP_VERSION = "38.00.00";
|
||||
const APP_VERSION = "39.00.00";
|
||||
const CACHE_NAME = `tarinai-colony-${APP_VERSION}`;
|
||||
const v = `v=${APP_VERSION}`;
|
||||
// Generated from app_manifest.json. Run scripts/generate_app_files.py after changing static files.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue