defmodule Odinsea.Channel.Handler.UI do @moduledoc """ Handles user interface interaction packets. Ported from: src/handling/channel/handler/UserInterfaceHandler.java ## Main Handlers - handle_cygnus_summon/2 - Cygnus/Aran first job advancement - handle_game_poll/2 - In-game poll - handle_ship_object/2 - Ship/boat object requests """ require Logger alias Odinsea.Net.Packet.In alias Odinsea.Game.{Character, Map} alias Odinsea.Channel.Packets # ============================================================================ # Job Advancement # ============================================================================ @doc """ Handles Cygnus/Aran summon NPC request (CP_CYGNUS_SUMMON / 0xC5). Opens the first job advancement NPC for Cygnus and Aran characters. - Job 2000 (Aran) → NPC 1202000 - Job 1000 (Cygnus Knight) → NPC 1101008 Reference: UserInterfaceHandler.CygnusSummon_NPCRequest() """ def handle_cygnus_summon(_packet, client_pid) do case Character.get_state_by_client(client_pid) do {:ok, character_id, char_state} -> npc_id = case char_state.job do 2000 -> 1202000 # Aran 1000 -> 1101008 # Cygnus Knight _ -> nil end if npc_id do # TODO: Start NPC script # NPCScriptManager.getInstance().start(c, npc_id) Logger.debug("Cygnus/Aran summon NPC: #{npc_id} for character #{character_id}") else Logger.debug("Invalid job for Cygnus summon: #{char_state.job}, character #{character_id}") end :ok {:error, reason} -> Logger.warn("Failed to handle Cygnus summon: #{inspect(reason)}") end end # ============================================================================ # Game Poll # ============================================================================ @doc """ Handles in-game poll (CP_GAME_POLL / 0xD4). Player submits response to server poll/questionnaire. Reference: UserInterfaceHandler.InGame_Poll() """ def handle_game_poll(packet, client_pid) do # tick = In.decode_int(packet) selection = In.decode_int(packet) case Character.get_state_by_client(client_pid) do {:ok, character_id, char_state} -> # TODO: Validate poll is enabled # TODO: Validate selection is valid # TODO: Record poll response # TODO: Send reply packet Logger.debug("Game poll response: #{selection}, character #{character_id}") :ok {:error, reason} -> Logger.warn("Failed to handle game poll: #{inspect(reason)}") end end # ============================================================================ # Ship/Boat Objects # ============================================================================ @doc """ Handles ship object request (CP_SHIP_OBJECT / 0x127). Client requests ship/boat status for station maps. Used for boats between continents (Ellinia-Orbis, etc.) Packet format varies by map: - BB 00 6C 24 05 06 00 - Ellinia - BB 00 6E 1C 4E 0E 00 - Leafre Reference: UserInterfaceHandler.ShipObjectRequest() """ def handle_ship_object(packet, client_pid) do # Map ID is encoded in the packet in various ways # The full packet structure varies by client version case Character.get_state_by_client(client_pid) do {:ok, character_id, char_state} -> map_id = char_state.map # Determine ship effect based on map effect = get_ship_effect(map_id) # TODO: Check event manager for actual docked status # Boats/Trains/Geenie/Flight managers Logger.debug("Ship object request: map #{map_id}, effect #{effect}, character #{character_id}") # TODO: Send boat packet with effect # c.sendPacket(MaplePacketCreator.boatPacket(effect)) :ok {:error, reason} -> Logger.warn("Failed to handle ship object: #{inspect(reason)}") end end # ============================================================================ # Helper Functions # ============================================================================ # Returns the ship effect value for a given map # Effect: 1 = Coming, 3 = Going, 1034 = Balrog defp get_ship_effect(map_id) do case map_id do # Ellinia Station >> Orbis 101000300 -> 3 # Orbis Station >> Ellinia 200000111 -> 3 # Orbis Station >> Ludi 200000121 -> 3 # Ludi Station >> Orbis 220000110 -> 3 # Orbis Station >> Ariant 200000151 -> 3 # Ariant Station >> Orbis 260000100 -> 3 # Leafre Station >> Orbis 240000110 -> 3 # Orbis Station >> Leafre 200000131 -> 3 # During boat rides 200090010 -> 1 # To Orbis 200090000 -> 1 # To Ellinia _ -> 3 # Default: going end end end