Files
odinsea-elixir/lib/odinsea/net/opcodes.ex
2026-02-14 23:58:01 -07:00

904 lines
24 KiB
Elixir

defmodule Odinsea.Net.Opcodes do
@moduledoc """
Packet opcodes for MapleStory GMS v342.
Directly ported from Java recvops.properties and sendops.properties.
All opcode values MUST match exactly for compatibility with the v342 client.
Naming conventions:
- Client → Server (recv): cp_* (Client Packet)
- Server → Client (send): lp_* (LoopBack Packet)
"""
# ==================================================================================================
# Client → Server (Recv Opcodes) - From recvops.properties
# ==================================================================================================
# Connection/Security
def cp_alive_ack(), do: 0x16
# Login/Account
def cp_client_hello(), do: 0x01
def cp_login_password(), do: 0x02
def cp_serverlist_request(), do: 0x04
def cp_charlist_request(), do: 0x05
def cp_serverstatus_request(), do: 0x06
def cp_check_char_name(), do: 0x0E
def cp_create_char(), do: 0x12
def cp_create_ultimate(), do: 0x14
def cp_delete_char(), do: 0x15
def cp_exception_log(), do: 0x17
def cp_security_packet(), do: 0x18
def cp_hardware_info(), do: 0x70
def cp_window_focus(), do: 0x71
def cp_char_select(), do: 0x19
def cp_auth_second_password(), do: 0x1A
def cp_rsa_key(), do: 0x20
def cp_client_dump_log(), do: 0x1D
def cp_create_security_handle(), do: 0x1E
def cp_select_world(), do: 0x03
def cp_check_user_limit(), do: 0x06
# Migration/Channel
def cp_player_loggedin(), do: 0x0D
def cp_change_map(), do: 0x23
def cp_change_channel(), do: 0x24
def cp_enter_cash_shop(), do: 0x25
def cp_enter_pvp(), do: 0x26
def cp_enter_pvp_party(), do: 0x27
def cp_leave_pvp(), do: 0x29
def cp_migrate_in(), do: 0x0D
def cp_enter_mts(), do: 0xB4
# Player Movement/Actions
def cp_move_player(), do: 0x2A
def cp_cancel_chair(), do: 0x2C
def cp_use_chair(), do: 0x2D
def cp_close_range_attack(), do: 0x2F
def cp_ranged_attack(), do: 0x30
def cp_magic_attack(), do: 0x31
def cp_passive_energy(), do: 0x32
def cp_take_damage(), do: 0x34
def cp_pvp_attack(), do: 0x35
def cp_general_chat(), do: 0x36
def cp_close_chalkboard(), do: 0x37
def cp_face_expression(), do: 0x38
def cp_face_android(), do: 0x39
def cp_use_itemeffect(), do: 0x3A
def cp_wheel_of_fortune(), do: 0x3B
def cp_char_info_request(), do: 0x75
def cp_spawn_pet(), do: 0x76
def cp_cancel_debuff(), do: 0x78
def cp_change_map_special(), do: 0x79
def cp_use_inner_portal(), do: 0x7B
def cp_trock_add_map(), do: 0x7C
# NPC Interaction
def cp_npc_talk(), do: 0x40
def cp_npc_move(), do: 0x41 # NPC animation/movement (added for compatibility)
def cp_npc_talk_more(), do: 0x42
def cp_npc_shop(), do: 0x43
def cp_storage(), do: 0x44
def cp_use_hired_merchant(), do: 0x45
def cp_merch_item_store(), do: 0x47
def cp_duey_action(), do: 0x48
def cp_mech_cancel(), do: 0x49
def cp_owl(), do: 0x4A
def cp_owl_warp(), do: 0x4B
# Inventory/Items
def cp_item_sort(), do: 0x4D
def cp_item_gather(), do: 0x4E
def cp_item_move(), do: 0x4F
def cp_move_bag(), do: 0x50
def cp_switch_bag(), do: 0x51
def cp_use_item(), do: 0x53
def cp_cancel_item_effect(), do: 0x54
def cp_use_summon_bag(), do: 0x56
def cp_pet_food(), do: 0x57
def cp_use_mount_food(), do: 0x58
def cp_use_scripted_npc_item(), do: 0x59
def cp_use_recipe(), do: 0x5A
def cp_use_cash_item(), do: 0x5B
def cp_use_catch_item(), do: 0x5D
def cp_use_skill_book(), do: 0x5E
def cp_use_owl_minerva(), do: 0x60
def cp_use_tele_rock(), do: 0x61
def cp_use_return_scroll(), do: 0x62
def cp_use_upgrade_scroll(), do: 0x63
def cp_use_flag_scroll(), do: 0x64
def cp_use_equip_scroll(), do: 0x65
def cp_use_potential_scroll(), do: 0x66
def cp_use_bag(), do: 0x68
def cp_use_magnify_glass(), do: 0x69
def cp_item_pickup(), do: 0x10C
# Stats/Skills
def cp_distribute_ap(), do: 0x6A
def cp_auto_assign_ap(), do: 0x6B
def cp_heal_over_time(), do: 0x6C
def cp_distribute_sp(), do: 0x6E
def cp_special_move(), do: 0x6F
def cp_cancel_buff(), do: 0x70
def cp_skill_effect(), do: 0x71
def cp_meso_drop(), do: 0x72
def cp_give_fame(), do: 0x73
def cp_skill_macro(), do: 0x84
def cp_change_keymap(), do: 0xB2
# Anti-Cheat
def cp_user_anti_macro_item_use_request(), do: 0x7D
def cp_user_anti_macro_skill_use_request(), do: 0x7E
def cp_user_anti_macro_question_result(), do: 0x7F
# Quests
def cp_quest_action(), do: 0x81
def cp_reward_item(), do: 0x86
def cp_update_quest(), do: 0x142
def cp_quest_item(), do: 0x143
def cp_use_item_quest(), do: 0x144
# Crafting
def cp_item_maker(), do: 0x87
def cp_repair_all(), do: 0x88
def cp_repair(), do: 0x89
def cp_solomon(), do: 0x8C
def cp_gach_exp(), do: 0x8D
def cp_craft_done(), do: 0xC8
def cp_craft_effect(), do: 0xC9
def cp_craft_make(), do: 0xCA
# Profession/Harvesting
def cp_profession_info(), do: 0x97
def cp_use_pot(), do: 0x98
def cp_clear_pot(), do: 0x99
def cp_feed_pot(), do: 0x9A
def cp_cure_pot(), do: 0x9B
def cp_reward_pot(), do: 0x9C
def cp_use_treasuer_chest(), do: 0x95
def cp_start_harvest(), do: 0x12E
def cp_stop_harvest(), do: 0x12F
def cp_make_extractor(), do: 0x114
# Social
def cp_partychat(), do: 0xA0
def cp_party_chat(), do: cp_partychat() # Alias for readability
def cp_whisper(), do: 0xA1
def cp_messenger(), do: 0xA2
def cp_player_interaction(), do: 0xA3
def cp_party_operation(), do: 0xA4
def cp_deny_party_request(), do: 0xA5
def cp_expedition_operation(), do: 0xA6
def cp_expedition_listing(), do: 0xA7
def cp_guild_operation(), do: 0xA8
def cp_deny_guild_request(), do: 0xA9
def cp_admin_command(), do: 0xAA
def cp_admin_log(), do: 0xAB
def cp_buddylist_modify(), do: 0xAC
def cp_note_action(), do: 0xAD
def cp_alliance_operation(), do: 0xBA
def cp_deny_alliance_request(), do: 0xBB
# Family
def cp_request_family(), do: 0xBC
def cp_open_family(), do: 0xBD
def cp_family_operation(), do: 0xBE
def cp_delete_junior(), do: 0xBF
def cp_delete_senior(), do: 0xC0
def cp_accept_family(), do: 0xC1
def cp_use_family(), do: 0xC2
def cp_family_precept(), do: 0xC3
def cp_family_summon(), do: 0xC4
def cp_cygnus_summon(), do: 0xC5
def cp_aran_combo(), do: 0xC6
# Misc
def cp_follow_request(), do: 0x8E
def cp_follow_reply(), do: 0x91
def cp_auto_follow_reply(), do: 0x92
def cp_report(), do: 0x94
def cp_pvp_respawn(), do: 0x9D
def cp_use_door(), do: 0xAF
def cp_use_mech_door(), do: 0xB0
def cp_rps_game(), do: 0xB3
def cp_ring_action(), do: 0xB5
def cp_bbs_operation(), do: 0xCD
def cp_transform_player(), do: 0xD2
def cp_xmas_surprise(), do: 0xD3
def cp_game_poll(), do: 0xD4
# Pets
def cp_move_pet(), do: 0xD7
def cp_pet_chat(), do: 0xD8
def cp_pet_command(), do: 0xD9
def cp_pet_loot(), do: 0xDA
def cp_pet_auto_pot(), do: 0xDB
# Summons
def cp_move_summon(), do: 0xDF
def cp_summon_attack(), do: 0xE0
def cp_damage_summon(), do: 0xE1
def cp_sub_summon(), do: 0xE2
def cp_remove_summon(), do: 0xE3
def cp_pvp_summon(), do: 0xE4
# Dragon/Android
def cp_move_dragon(), do: 0xE7
def cp_move_android(), do: 0xEA
def cp_quick_slot(), do: 0xED
def cp_pam_song(), do: 0xF0
# Mobs/Life
def cp_move_life(), do: 0xF7
def cp_auto_aggro(), do: 0xF8
def cp_friendly_damage(), do: 0xFB
def cp_monster_bomb(), do: 0xFC
def cp_hypnotize_dmg(), do: 0xFD
def cp_mob_skill_delay_end(), do: 0xFE
def cp_mob_bomb(), do: 0xFF
def cp_mob_node(), do: 0x100
def cp_display_node(), do: 0x101
def cp_npc_action(), do: 0x106
# Reactors
def cp_damage_reactor(), do: 0x10F
def cp_touch_reactor(), do: 0x110
# Events/Games
def cp_snowball(), do: 0x119
def cp_left_knock_back(), do: 0x11A
def cp_coconut(), do: 0x11B
def cp_monster_carnival(), do: 0x125
def cp_ship_object(), do: 0x127
def cp_party_search_start(), do: 0x129
def cp_party_search_stop(), do: 0x12A
# Cash Shop
def cp_cs_update(), do: 0x135
def cp_buy_cs_item(), do: 0x136
def cp_coupon_code(), do: 0x137
# MTS
def cp_mapletv(), do: 0x140
def cp_touching_mts(), do: 0x159
def cp_mts_tab(), do: 0x15A
# Custom (server-specific)
def cp_inject_packet(), do: 0x5002
def cp_set_code_page(), do: 0x5003
# Special (negative offsets from other opcodes)
def cp_change_set(), do: 0x7FFE
def cp_get_book_info(), do: 0x7FFA
def cp_reissue_medal(), do: 0x7FFB
def cp_click_reactor(), do: 0x7FFC
# ==================================================================================================
# Server → Client (Send Opcodes) - From sendops.properties
# ==================================================================================================
# General
def lp_alive_req(), do: 0x0D
def lp_enable_action(), do: 0x0C
def lp_set_field(), do: 0x14
def lp_set_cash_shop_opened(), do: 0x15
def lp_migrate_command(), do: 0x16
# Login
def lp_login_status(), do: 0x01
def lp_serverstatus(), do: 0x03
def lp_serverlist(), do: 0x06
def lp_charlist(), do: 0x07
def lp_server_ip(), do: 0x08
def lp_char_name_response(), do: 0x09
def lp_add_new_char_entry(), do: 0x0A
def lp_delete_char_response(), do: 0x0B
def lp_change_channel(), do: 0x0C
def lp_cs_use(), do: 0x0E
def lp_channel_selected(), do: 0x10
def lp_relog_response(), do: 0x12
def lp_rsa_key(), do: 0x13
def lp_enable_recommended(), do: 0x15
def lp_send_recommended(), do: 0x16
def lp_login_auth(), do: 0x17
def lp_secondpw_error(), do: 0x18
# Inventory/Stats
def lp_modify_inventory_item(), do: 0x19
def lp_update_inventory_slot(), do: 0x1A
def lp_update_stats(), do: 0x1B
def lp_give_buff(), do: 0x1C
def lp_cancel_buff(), do: 0x1D
def lp_temp_stats(), do: 0x1E
def lp_temp_stats_reset(), do: 0x1F
def lp_update_skills(), do: 0x20
def lp_fame_response(), do: 0x22
def lp_show_status_info(), do: 0x23
def lp_show_notes(), do: 0x24
def lp_trock_locations(), do: 0x25
def lp_anti_macro_result(), do: 0x26
def lp_update_mount(), do: 0x2B
def lp_show_quest_completion(), do: 0x2C
def lp_send_title_box(), do: 0x2D
def lp_fishing_store(), do: 0x2E
def lp_use_skill_book(), do: 0x2F
def lp_sp_reset(), do: 0x30
def lp_report(), do: 0x31
def lp_finish_sort(), do: 0x33
def lp_finish_gather(), do: 0x34
def lp_char_info(), do: 0x37
# Social/Party/Guild
def lp_party_operation(), do: 0x38
def lp_expedition_operation(), do: 0x3A
def lp_buddylist(), do: 0x3B
def lp_guild_operation(), do: 0x3D
def lp_alliance_operation(), do: 0x3E
# Map Effects/Environment
def lp_spawn_portal(), do: 0x3F
def lp_mech_portal(), do: 0x40
def lp_servermessage(), do: 0x41
def lp_pigmi_reward(), do: 0x42
def lp_owl_of_minerva(), do: 0x43
def lp_engage_request(), do: 0x45
def lp_engage_result(), do: 0x46
def lp_yellow_chat(), do: 0x4A
def lp_shop_discount(), do: 0x4B
def lp_catch_mob(), do: 0x4C
def lp_fishing_board_update(), do: 0x55
def lp_bbs_operation(), do: 0x56
def lp_avatar_mega(), do: 0x58
def lp_player_npc(), do: 0x5D
# Special Systems
def lp_energy(), do: 0x69
def lp_ghost_point(), do: 0x6A
def lp_ghost_status(), do: 0x6B
def lp_fairy_pend_msg(), do: 0x6C
# Family
def lp_send_pedigree(), do: 0x6D
def lp_open_family(), do: 0x6E
def lp_family_message(), do: 0x6F
def lp_family_invite(), do: 0x70
def lp_family_junior(), do: 0x71
def lp_senior_message(), do: 0x72
def lp_family(), do: 0x73
def lp_rep_increase(), do: 0x74
def lp_family_loggedin(), do: 0x75
def lp_family_buff(), do: 0x76
def lp_family_use_request(), do: 0x77
def lp_level_update(), do: 0x78
def lp_marriage_update(), do: 0x79
def lp_job_update(), do: 0x7A
def lp_pendant_slot(), do: 0x7B
# Misc UI/Messages
def lp_follow_request(), do: 0x7C
def lp_top_msg(), do: 0x7E
def lp_mid_msg(), do: 0x7F
def lp_clear_mid_msg(), do: 0x80
def lp_update_jaguar(), do: 0x82
def lp_ultimate_explorer(), do: 0x84
def lp_gm_police(), do: 0x88
def lp_pam_song(), do: 0x89
def lp_profession_info(), do: 0x8B
def lp_item_pot(), do: 0x8D
def lp_skill_macro(), do: 0x8F
# Warps/Shops
def lp_warp_to_map(), do: 0x90
def lp_mts_open(), do: 0x91
def lp_cs_open(), do: 0x92
def lp_login_welcome(), do: 0x94
def lp_server_blocked(), do: 0x97
def lp_pvp_blocked(), do: 0x98
# Effects
def lp_show_equip_effect(), do: 0x99
def lp_multichat(), do: 0x9A
def lp_whisper(), do: 0x9B
def lp_boss_env(), do: 0x9D
def lp_move_env(), do: 0x9E
def lp_update_env(), do: 0x9F
def lp_map_effect(), do: 0xA1
def lp_cash_song(), do: 0xA2
def lp_gm_effect(), do: 0xA3
def lp_ox_quiz(), do: 0xA4
def lp_gmevent_instructions(), do: 0xA5
def lp_clock(), do: 0xA6
def lp_boat_eff(), do: 0xA7
def lp_boat_effect(), do: 0xA8
def lp_stop_clock(), do: 0xAC
# Mini-games
def lp_pyramid_update(), do: 0xAF
def lp_pyramid_result(), do: 0xB0
def lp_quick_slot(), do: 0xB1
def lp_move_platform(), do: 0xB2
# PVP
def lp_pvp_info(), do: 0xB6
def lp_public_npc(), do: 0xB7
# Players
def lp_spawn_player(), do: 0xB8
def lp_remove_player_from_map(), do: 0xB9
def lp_chattext(), do: 0xBA
def lp_chalkboard(), do: 0xBC
def lp_update_char_box(), do: 0xBD
def lp_show_scroll_effect(), do: 0xBF
def lp_show_potential_effect(), do: 0xC1
def lp_show_potential_reset(), do: 0xC2
def lp_player_damaged(), do: 0xC3
def lp_pvp_attack(), do: 0xC4
def lp_pvp_mist(), do: 0xC5
def lp_pvp_cool(), do: 0xC6
def lp_tesla_triangle(), do: 0xC7
def lp_fishing_caught(), do: 0xC8
def lp_pams_song(), do: 0xC9
def lp_follow_effect(), do: 0xCA
def lp_craft_effect(), do: 0xCC
def lp_craft_complete(), do: 0xCD
def lp_harvested(), do: 0xCE
# Pets
def lp_spawn_pet(), do: 0xD1
def lp_move_pet(), do: 0xD4
def lp_pet_chat(), do: 0xD5
def lp_pet_namechange(), do: 0xD6
def lp_pet_update(), do: 0xD7
def lp_pet_command(), do: 0xD8
# Dragon/Android
def lp_dragon_spawn(), do: 0xD9
def lp_dragon_move(), do: 0xDA
def lp_dragon_remove(), do: 0xDB
def lp_android_spawn(), do: 0xDC
def lp_android_move(), do: 0xDD
def lp_android_emotion(), do: 0xDE
def lp_android_remove(), do: 0xDF
def lp_android_deactivated(), do: 0xE0
# Player Actions
def lp_move_player(), do: 0xE2
def lp_close_range_attack(), do: 0xE4
def lp_ranged_attack(), do: 0xE5
def lp_magic_attack(), do: 0xE6
def lp_energy_attack(), do: 0xE7
def lp_skill_effect(), do: 0xE8
def lp_cancel_skill_effect(), do: 0xEA
def lp_damage_player(), do: 0xEB
def lp_facial_expression(), do: 0xEC
def lp_show_item_effect(), do: 0xED
def lp_show_chair(), do: 0xF0
def lp_update_char_look(), do: 0xF1
def lp_show_foreign_effect(), do: 0xF2
def lp_give_foreign_buff(), do: 0xF3
def lp_cancel_foreign_buff(), do: 0xF4
def lp_update_partymember_hp(), do: 0xF5
def lp_load_guild_name(), do: 0xF6
def lp_load_guild_icon(), do: 0xF7
def lp_load_team(), do: 0xF8
def lp_show_harvest(), do: 0xF9
def lp_pvp_hp(), do: 0xFA
def lp_cancel_chair(), do: 0xFC
def lp_show_item_gain_inchat(), do: 0xFF
def lp_current_map_warp(), do: 0x100
def lp_mesobag_success(), do: 0x101
def lp_mesobag_failure(), do: 0x102
def lp_update_quest_info(), do: 0x104
def lp_buff_bar(), do: 0x108
def lp_pet_flag_change(), do: 0x10A
# Repair
def lp_repair_window(), do: 0x115
def lp_cygnus_intro_lock(), do: 0x116
def lp_cygnus_intro_disable_ui(), do: 0x117
def lp_summon_hint(), do: 0x118
def lp_summon_hint_msg(), do: 0x119
def lp_aran_combo(), do: 0x11A
def lp_aran_combo_recharge(), do: 0x11B
def lp_game_poll_reply(), do: 0x11E
def lp_spouse_message(), do: 0x11F
def lp_follow_move(), do: 0x124
def lp_follow_msg(), do: 0x125
def lp_game_poll_question(), do: 0x127
def lp_create_ultimate(), do: 0x128
def lp_harvest_message(), do: 0x129
def lp_open_bag(), do: 0x12B
def lp_dragon_blink(), do: 0x12D
def lp_pvp_icegage(), do: 0x12E
def lp_cooldown(), do: 0x12F
# Summons
def lp_spawn_summon(), do: 0x131
def lp_remove_summon(), do: 0x132
def lp_move_summon(), do: 0x133
def lp_summon_attack(), do: 0x134
def lp_pvp_summon(), do: 0x135
def lp_summon_skill(), do: 0x136
def lp_damage_summon(), do: 0x137
# Monsters
def lp_spawn_monster(), do: 0x13A
def lp_kill_monster(), do: 0x13B
def lp_spawn_monster_control(), do: 0x13C
def lp_move_monster(), do: 0x13D
def lp_move_monster_response(), do: 0x13E
def lp_apply_monster_status(), do: 0x140
def lp_cancel_monster_status(), do: 0x141
def lp_mob_to_mob_damage(), do: 0x142
def lp_damage_monster(), do: 0x144
def lp_show_monster_hp(), do: 0x148
def lp_show_magnet(), do: 0x149
def lp_catch_monster(), do: 0x14A
def lp_monster_properties(), do: 0x14D
def lp_remove_talk_monster(), do: 0x14E
def lp_talk_monster(), do: 0x14F
# NPCs
def lp_spawn_npc(), do: 0x156
def lp_remove_npc(), do: 0x157
def lp_spawn_npc_request_controller(), do: 0x158
def lp_npc_action(), do: 0x159
def lp_npc_set_script(), do: 0x15F
# Merchants
def lp_spawn_hired_merchant(), do: 0x161
def lp_destroy_hired_merchant(), do: 0x162
def lp_update_hired_merchant(), do: 0x163
# Map Objects
def lp_drop_item_from_mapobject(), do: 0x165
def lp_remove_item_from_map(), do: 0x167
def lp_spawn_mist(), do: 0x16B
def lp_remove_mist(), do: 0x16C
def lp_spawn_door(), do: 0x16D
def lp_remove_door(), do: 0x16E
def lp_mech_door_spawn(), do: 0x16F
def lp_mech_door_remove(), do: 0x170
# Reactors
def lp_reactor_hit(), do: 0x171
def lp_reactor_spawn(), do: 0x173
def lp_reactor_destroy(), do: 0x174
def lp_spawn_extractor(), do: 0x176
def lp_remove_extractor(), do: 0x177
# Mini-games/Events
def lp_roll_snowball(), do: 0x178
def lp_hit_snowball(), do: 0x179
def lp_snowball_message(), do: 0x17A
def lp_left_knock_back(), do: 0x17B
def lp_hit_coconut(), do: 0x17C
def lp_coconut_score(), do: 0x17D
def lp_monster_carnival_start(), do: 0x180
def lp_monster_carnival_obtained_cp(), do: 0x181
def lp_monster_carnival_party_cp(), do: 0x182
def lp_monster_carnival_summon(), do: 0x183
def lp_monster_carnival_died(), do: 0x186
def lp_chaos_horntail_shrine(), do: 0x18E
def lp_chaos_zakum_shrine(), do: 0x18F
def lp_horntail_shrine(), do: 0x190
def lp_english_quiz(), do: 0x191
# PVP (continued)
def lp_pvp_type(), do: 0x192
def lp_pvp_transform(), do: 0x193
def lp_pvp_enabled(), do: 0x195
def lp_pvp_score(), do: 0x196
def lp_pvp_result(), do: 0x197
def lp_pvp_team(), do: 0x198
def lp_pvp_scoreboard(), do: 0x199
def lp_pvp_points(), do: 0x19B
def lp_pvp_killed(), do: 0x19C
def lp_pvp_mode(), do: 0x19D
def lp_pvp_iceknight(), do: 0x19E
def lp_capture_flags(), do: 0x19F
def lp_capture_position(), do: 0x1A0
def lp_capture_reset(), do: 0x1A1
# NPC/Shop Interactions
def lp_npc_talk(), do: 0x1A3
def lp_open_npc_shop(), do: 0x1A5
def lp_confirm_shop_transaction(), do: 0x1A6
def lp_open_storage(), do: 0x1A9
def lp_merch_item_msg(), do: 0x1AA
def lp_merch_item_store(), do: 0x1AB
def lp_rps_game(), do: 0x1AC
def lp_messenger(), do: 0x1AD
def lp_player_interaction(), do: 0x1AE
def lp_duey(), do: 0x1B6
# Cash Shop
def lp_cs_update(), do: 0x1B8
def lp_cs_operation(), do: 0x1B9
def lp_xmas_surprise(), do: 0x1BD
# Input
def lp_keymap(), do: 0x1C5
def lp_pet_auto_hp(), do: 0x1C6
def lp_pet_auto_mp(), do: 0x1C7
# TV/MTS
def lp_start_tv(), do: 0x1CD
def lp_remove_tv(), do: 0x1CE
def lp_enable_tv(), do: 0x1CF
def lp_vicious_hammer(), do: 0x1D3
def lp_get_mts_tokens(), do: 0x1D7
def lp_mts_operation(), do: 0x1D8
# Custom (server-specific)
def lp_damage_skin(), do: 0x5000
def lp_open_website(), do: 0x5001
def lp_perfect_pitch(), do: 0x5002
def lp_get_code_page(), do: 0x5003
# Special (calculated/custom offsets)
def lp_block_portal(), do: 0x7FFA
def lp_ariant_scoreboard(), do: 0x7FFB
def lp_player_hint(), do: 0x7FFC
def lp_ariant_thing(), do: 0x7FFD
def lp_ariant_pq_start(), do: 0x7FAE
def lp_npc_confirm(), do: 0x7FBE
def lp_pin_assigned(), do: 0x7FCE
def lp_all_charlist(), do: 0x7FDE
def lp_get_card(), do: 0x7FEE
def lp_card_set(), do: 0x7FEE
def lp_book_stats(), do: 0x7FEA
def lp_book_info(), do: 0x7FEB
def lp_party_search(), do: 0x7FEC
def lp_member_search(), do: 0x7FED
# ==================================================================================================
# Helper Functions
# ==================================================================================================
@doc """
Returns a human-readable name for a given opcode value.
Useful for debugging and logging.
"""
def name_for(opcode) when is_integer(opcode) do
case opcode do
# Client opcodes (common ones for debugging)
0x01 -> "CP_CLIENT_HELLO"
0x02 -> "CP_LOGIN_PASSWORD"
0x0D -> "CP_PLAYER_LOGGEDIN"
0x19 -> "CP_CHAR_SELECT"
0x23 -> "CP_CHANGE_MAP"
0x24 -> "CP_CHANGE_CHANNEL"
0x2A -> "CP_MOVE_PLAYER"
0x36 -> "CP_GENERAL_CHAT"
0x40 -> "CP_NPC_TALK"
0xA0 -> "CP_PARTYCHAT"
0xA1 -> "CP_WHISPER"
# Server opcodes (common ones for debugging)
0x01 -> "LP_LOGIN_STATUS"
0x06 -> "LP_SERVERLIST"
0x07 -> "LP_CHARLIST"
0x0D -> "LP_ALIVE_REQ"
0xB8 -> "LP_SPAWN_PLAYER"
0xB9 -> "LP_REMOVE_PLAYER_FROM_MAP"
0xBA -> "LP_CHATTEXT"
0xE2 -> "LP_MOVE_PLAYER"
0x9A -> "LP_MULTICHAT"
0x9B -> "LP_WHISPER"
0x1A3 -> "LP_NPC_TALK"
_ -> "UNKNOWN_0x#{Integer.to_string(opcode, 16) |> String.upcase()}"
end
end
@doc """
Validates if an opcode is a known client packet.
"""
def valid_client_opcode?(opcode) when is_integer(opcode) do
opcode in [
# Add all valid client opcodes here for validation
0x01,
0x02,
0x04,
0x05,
0x06,
0x0D,
0x0E,
0x12,
0x14,
0x15,
0x16,
0x17,
0x18,
0x19,
0x1A,
0x1D,
0x1E,
0x20,
0x23,
0x24,
0x25,
0x26,
0x27,
0x29,
0x2A,
0x2C,
0x2D,
0x2F,
0x30,
0x31,
0x32,
0x34,
0x35,
0x36,
0x37,
0x38,
0x39,
0x3A,
0x3B,
0x40,
0x42,
0x43,
0x44,
0x45,
0x47,
0x48,
0x49,
0x4A,
0x4B,
0x4D,
0x4E,
0x4F,
0x50,
0x51,
0x53,
0x54,
0x56,
0x57,
0x58,
0x59,
0x5A,
0x5B,
0x5D,
0x5E,
0x60,
0x61,
0x62,
0x63,
0x64,
0x65,
0x66,
0x68,
0x69,
0x6A,
0x6B,
0x6C,
0x6E,
0x6F,
0x70,
0x71,
0x72,
0x73,
0x75,
0x76,
0x78,
0x79,
0x7B,
0x7C,
0x7D,
0x7E,
0x7F,
0x81,
0x84,
0x86,
0x87,
0x88,
0x89,
0x8C,
0x8D,
0x8E,
0x91,
0x92,
0x94,
0x95,
0x97,
0x98,
0x99,
0x9A,
0x9B,
0x9C,
0x9D,
0xA0,
0xA1,
0xA2,
0xA3,
0xA4,
0xA5,
0xA6,
0xA7,
0xA8,
0xA9,
0xAA,
0xAB,
0xAC,
0xAD,
0xAF,
0xB0,
0xB2,
0xB3,
0xB4,
0xB5,
0xBA,
0xBB,
0xBC,
0xBD,
0xBE,
0xBF,
0xC0,
0xC1,
0xC2,
0xC3,
0xC4,
0xC5,
0xC6,
0xC8,
0xC9,
0xCA,
0xCD,
0xD2,
0xD3,
0xD4,
0xD7,
0xD8,
0xD9,
0xDA,
0xDB,
0xDF,
0xE0,
0xE1,
0xE2,
0xE3,
0xE4,
0xE7,
0xEA,
0xED,
0xF0,
0xF7,
0xF8,
0xFB,
0xFC,
0xFD,
0xFE,
0xFF,
0x100,
0x101,
0x106,
0x10C,
0x10F,
0x110,
0x114,
0x119,
0x11A,
0x11B,
0x125,
0x127,
0x129,
0x12A,
0x12E,
0x12F,
0x135,
0x136,
0x137,
0x140,
0x142,
0x143,
0x144,
0x159,
0x15A
]
end
def valid_client_opcode?(_), do: false
end