P24-02: 操作と通知の全受入
This commit is contained in:
+126
-9
@@ -152,6 +152,11 @@ var important_warning_cutin: OperationFeedback.ImportantWarningCutinDialog
|
||||
var front_button: Button
|
||||
var back_button: Button
|
||||
var excavation_button: Button
|
||||
var demolition_button: Button
|
||||
var demolition_dialog: ConfirmationDialog
|
||||
var _demolition_mode := false
|
||||
var _demolition_target: StringName = &""
|
||||
var _pending_demolition_commands: Dictionary = {}
|
||||
var pan_button: Button
|
||||
var pause_button: Button
|
||||
var speed_buttons: Dictionary = {}
|
||||
@@ -812,12 +817,20 @@ func _create_bottom_bar() -> Control:
|
||||
palette_scroll.custom_minimum_size.y = 62
|
||||
palette_scroll.visible = false
|
||||
column.add_child(palette_scroll)
|
||||
var palette_row := HBoxContainer.new()
|
||||
palette_row.name = "BuildPaletteRow"
|
||||
palette_row.add_theme_constant_override("separation", 4)
|
||||
palette_scroll.add_child(palette_row)
|
||||
var grid := GridContainer.new()
|
||||
grid.name = "BuildPalette"
|
||||
grid.columns = MVP_FACILITY_IDS.size()
|
||||
grid.add_theme_constant_override("h_separation", 4)
|
||||
grid.add_theme_constant_override("v_separation", 0)
|
||||
palette_scroll.add_child(grid)
|
||||
palette_row.add_child(grid)
|
||||
demolition_button = _button("撤去", _toggle_demolition_mode, 72)
|
||||
demolition_button.name = "DemolitionButton"
|
||||
demolition_button.toggle_mode = true
|
||||
palette_row.add_child(demolition_button)
|
||||
|
||||
build_status_label = Label.new()
|
||||
build_status_label.name = "BuildStatusLabel"
|
||||
@@ -1267,6 +1280,7 @@ func _select_build_definition(definition_id: StringName) -> void:
|
||||
if definition == null:
|
||||
_set_status("選択した施設定義が見つかりません。", false)
|
||||
return
|
||||
_set_demolition_mode(false, false)
|
||||
_set_excavation_mode(false, false)
|
||||
_set_pan_mode(false)
|
||||
_selected_definition_id = definition_id
|
||||
@@ -1293,6 +1307,9 @@ func _clear_build_selection(announce := true) -> void:
|
||||
|
||||
|
||||
func _clear_active_tool() -> void:
|
||||
if _demolition_mode:
|
||||
_set_demolition_mode(false)
|
||||
return
|
||||
if world_preview.pan_mode:
|
||||
_set_pan_mode(false)
|
||||
_set_status("画面移動を解除しました。施設をクリックすると情報を表示します。", true, true)
|
||||
@@ -1325,6 +1342,7 @@ func _toggle_pan_mode() -> void:
|
||||
|
||||
func _set_pan_mode(enabled: bool) -> void:
|
||||
if enabled:
|
||||
_set_demolition_mode(false, false)
|
||||
_clear_build_selection(false)
|
||||
_set_excavation_mode(false, false)
|
||||
_set_build_palette_open(false)
|
||||
@@ -1335,6 +1353,7 @@ func _set_pan_mode(enabled: bool) -> void:
|
||||
|
||||
func _set_excavation_mode(enabled: bool, announce := true) -> void:
|
||||
if enabled:
|
||||
_set_demolition_mode(false, false)
|
||||
_set_pan_mode(false)
|
||||
_excavation_mode = enabled
|
||||
if excavation_button != null:
|
||||
@@ -1380,6 +1399,9 @@ func _rotate_build_preview() -> void:
|
||||
func _on_map_cell_clicked(cell: Vector3i) -> void:
|
||||
if _audio_feedback != null:
|
||||
_audio_feedback.request_click()
|
||||
if _demolition_mode:
|
||||
_preview_demolition(cell)
|
||||
return
|
||||
if _excavation_mode:
|
||||
_start_excavation(cell)
|
||||
return
|
||||
@@ -2128,7 +2150,19 @@ func _preview_failure_message(report: Dictionary) -> String:
|
||||
var codes_value: Variant = report.get(&"error_codes", [])
|
||||
if codes_value is Array and not codes_value.is_empty():
|
||||
var code := String(codes_value[0])
|
||||
return "配置不可: %s" % PREVIEW_REASON_NAMES.get(code, code)
|
||||
if PREVIEW_REASON_NAMES.has(code):
|
||||
return "配置不可: %s" % PREVIEW_REASON_NAMES[code]
|
||||
var code_reasons: Variant = report.get(&"reasons", [])
|
||||
if code_reasons is Array and not code_reasons.is_empty():
|
||||
var reason: Variant = code_reasons[0]
|
||||
for candidate: Variant in code_reasons:
|
||||
if candidate is Dictionary and String(candidate.get(&"code", "")) == code:
|
||||
reason = candidate
|
||||
break
|
||||
if reason is Dictionary:
|
||||
var message := String(reason.get(&"message", ""))
|
||||
if not message.is_empty():
|
||||
return "配置不可: %s" % message
|
||||
var reasons_value: Variant = report.get(&"reasons", [])
|
||||
if reasons_value is Array and not reasons_value.is_empty() and reasons_value[0] is Dictionary:
|
||||
return "配置不可: %s" % String(reasons_value[0].get(&"message", "条件を満たしていません"))
|
||||
@@ -2358,6 +2392,8 @@ func _apply_loaded_interface(result: Dictionary) -> void:
|
||||
if _audio_feedback != null:
|
||||
_audio_feedback.begin_loaded_epoch(_current_audio_foreground())
|
||||
_pending_build_commands.clear()
|
||||
_pending_demolition_commands.clear()
|
||||
_set_demolition_mode(false, false)
|
||||
_pending_excavation_commands.clear()
|
||||
_pending_hire_commands.clear()
|
||||
_pending_elevator_commands.clear()
|
||||
@@ -2598,6 +2634,10 @@ func _on_snapshot_published(_snapshot: Dictionary = {}, _digest: String = "") ->
|
||||
func _on_command_completed(result: Variant) -> void:
|
||||
if result == null:
|
||||
return
|
||||
if _pending_demolition_commands.has(int(result.command_id)):
|
||||
_pending_demolition_commands.erase(int(result.command_id))
|
||||
_show_demolition_result(result)
|
||||
return
|
||||
if _pending_related_commands.has(int(result.command_id)):
|
||||
_pending_related_commands.erase(int(result.command_id))
|
||||
_set_status("関連施設の設定を反映しました。" if result.is_success() else result.message, result.is_success())
|
||||
@@ -2781,17 +2821,17 @@ func _phase_name(phase: GameClock.Phase) -> String:
|
||||
return "夜"
|
||||
|
||||
|
||||
const RESOURCE_TITLES := {&"gold": "所持金", &"mana": "マナ", &"materials": "資材", &"faith": "信仰"}
|
||||
|
||||
func _resource_title(resource_name: StringName) -> String:
|
||||
return String(RESOURCE_TITLES.get(resource_name, String(resource_name)))
|
||||
|
||||
|
||||
func _on_resource_changed(resource_name: StringName, value: int) -> void:
|
||||
if not resource_labels.has(resource_name):
|
||||
return
|
||||
var titles := {
|
||||
&"gold": "所持金",
|
||||
&"mana": "マナ",
|
||||
&"materials": "資材",
|
||||
&"faith": "信仰",
|
||||
}
|
||||
var label := resource_labels[resource_name] as Label
|
||||
label.text = "%s %d" % [titles[resource_name], value]
|
||||
label.text = "%s %d" % [_resource_title(resource_name), value]
|
||||
if resource_name == &"mana":
|
||||
label.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
label.tooltip_text = "残量0で全館停止。接客・調理・搬入・エレベーターと新規入館が停止します。\n残量と配電が回復すると再開します。破壊・摘発による休止は解除されません。"
|
||||
@@ -3114,6 +3154,83 @@ func _submit_ui_command(
|
||||
return _audio_feedback.submit_command(command_type, payload, actor_id, target_id, priority, execute_at, idempotency_key)
|
||||
return _runtime.call(&"submit_command", command_type, payload, actor_id, target_id, priority, execute_at, idempotency_key)
|
||||
|
||||
func _toggle_demolition_mode() -> void:
|
||||
_set_demolition_mode(not _demolition_mode)
|
||||
|
||||
|
||||
func _set_demolition_mode(enabled: bool, announce := true) -> void:
|
||||
if enabled:
|
||||
_set_pan_mode(false)
|
||||
_set_excavation_mode(false, false)
|
||||
_clear_build_selection(false)
|
||||
_demolition_mode = enabled
|
||||
_demolition_target = &""
|
||||
if demolition_dialog != null:
|
||||
demolition_dialog.hide()
|
||||
if demolition_button != null:
|
||||
demolition_button.set_pressed_no_signal(enabled)
|
||||
if world_preview != null:
|
||||
world_preview.set_demolition_mode(enabled)
|
||||
if announce:
|
||||
_set_status("撤去する施設のマスを選択してください。確認画面で取り消せます。" if enabled else "撤去モードを解除しました。", true, true)
|
||||
|
||||
|
||||
func _preview_demolition(cell: Vector3i) -> void:
|
||||
# Selection only; Runtime owns eligibility, occupancy and refunds.
|
||||
_demolition_target = world_preview.facility_at_canvas(world_preview.cell_to_canvas(cell))
|
||||
world_preview.selected_entity_id = _demolition_target
|
||||
if demolition_dialog == null:
|
||||
demolition_dialog = ConfirmationDialog.new()
|
||||
demolition_dialog.name = "DemolitionDialog"
|
||||
demolition_dialog.title = "施設の撤去"
|
||||
demolition_dialog.ok_button_text = "撤去する"
|
||||
demolition_dialog.cancel_button_text = "戻る"
|
||||
demolition_dialog.confirmed.connect(_confirm_demolition)
|
||||
demolition_dialog.canceled.connect(_cancel_demolition)
|
||||
add_child(demolition_dialog)
|
||||
_apply_button_style(demolition_dialog.get_ok_button())
|
||||
_apply_button_style(demolition_dialog.get_cancel_button())
|
||||
demolition_dialog.dialog_text = "座標 (%d, %d / %d)\n施設: %s\n\n撤去を指示しますか?" % [cell.x, cell.y, cell.z, String(_demolition_target)]
|
||||
demolition_dialog.popup_centered(Vector2i(420, 210))
|
||||
|
||||
|
||||
func _cancel_demolition() -> void:
|
||||
_demolition_target = &""
|
||||
_set_status("撤去を取り消しました。", true, true)
|
||||
|
||||
|
||||
func _confirm_demolition() -> void:
|
||||
if not _demolition_mode:
|
||||
return
|
||||
if _runtime == null or not _runtime.has_method(&"submit_command"):
|
||||
_set_status("Simulation Runtimeへ接続できません。", false)
|
||||
return
|
||||
var target := _demolition_target
|
||||
_demolition_target = &""
|
||||
var result: CommandResult = _runtime.submit_command(&"demolish_facility", {&"instance_id": target})
|
||||
# Paused play returns execution synchronously; running play returns acceptance.
|
||||
if result.is_success() and _runtime.command_queue.get_processed_result(result.command_id) == null:
|
||||
_pending_demolition_commands[result.command_id] = target
|
||||
_set_status("撤去を受け付けました", true)
|
||||
return
|
||||
_show_demolition_result(result)
|
||||
|
||||
|
||||
func _show_demolition_result(result: CommandResult) -> void:
|
||||
if result.is_success():
|
||||
var refund: Dictionary = result.details.get(&"refund", {})
|
||||
var keys: Array = refund.keys()
|
||||
keys.sort()
|
||||
var amounts: PackedStringArray = []
|
||||
for key: Variant in keys:
|
||||
if int(refund[key]) != 0:
|
||||
amounts.append("%s %d" % [_resource_title(StringName(key)), int(refund[key])])
|
||||
_set_status("撤去しました(返金: %s)" % "、".join(amounts) if not amounts.is_empty() else "撤去しました(返金なし)", true)
|
||||
else:
|
||||
_set_status("撤去できません: " + result.message, false)
|
||||
_refresh_selected_entity()
|
||||
world_preview.queue_redraw()
|
||||
|
||||
|
||||
func assign_staff_by_click(facility_id: StringName, staff_id: StringName = &"") -> void:
|
||||
if staff_management_panel == null:
|
||||
|
||||
+698
-131
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user