1494 lines
37 KiB
Elixir
1494 lines
37 KiB
Elixir
defmodule Odinsea.Scripting.PlayerAPI do
|
|
@moduledoc """
|
|
Player Interaction API for scripts.
|
|
|
|
This module provides the interface that scripts use to interact with
|
|
players, including dialogue functions, warping, item manipulation, and
|
|
game mechanics.
|
|
|
|
## API Objects
|
|
|
|
Different script types receive this API with different variable names:
|
|
- `cm` - Conversation manager (NPC/Quest scripts)
|
|
- `pi` - Portal interaction (Portal scripts)
|
|
- `rm` - Reactor manager (Reactor scripts)
|
|
- `qm` - Quest manager (Quest scripts - same as cm)
|
|
|
|
## Dialogue Functions
|
|
|
|
### Basic Dialogs
|
|
- `send_ok/1` - Show OK button dialog
|
|
- `send_next/1` - Show Next button dialog
|
|
- `send_prev/1` - Show Previous button dialog
|
|
- `send_next_prev/1` - Show Next and Previous buttons
|
|
|
|
### Choice Dialogs
|
|
- `send_yes_no/1` - Yes/No choice
|
|
- `send_accept_decline/1` - Accept/Decline choice
|
|
- `send_simple/1` - Menu selection with #L tags
|
|
|
|
### Input Dialogs
|
|
- `send_get_text/1` - Text input
|
|
- `send_get_number/4` - Number input with min/max
|
|
- `send_style/2` - Style selection (hair/face)
|
|
- `ask_avatar/2` - Avatar preview
|
|
|
|
### Player-to-NPC Dialogs (Speaker)
|
|
- `send_next_s/2` - Next with speaker type
|
|
- `send_ok_s/2` - OK with speaker type
|
|
- `send_yes_no_s/2` - Yes/No with speaker type
|
|
|
|
## Player Actions
|
|
|
|
### Warping
|
|
- `warp/1` - Warp to map (random portal)
|
|
- `warp/2` - Warp to map with specific portal
|
|
- `warp_instanced/1` - Warp to event instance map
|
|
|
|
### Items
|
|
- `gain_item/2` - Give/take items
|
|
- `gain_item_period/3` - Give item with expiration
|
|
- `have_item/1` - Check if player has item
|
|
- `can_hold/1` - Check if player can hold item
|
|
|
|
### Stats
|
|
- `gain_meso/1` - Give/take meso
|
|
- `gain_exp/1` - Give EXP
|
|
- `change_job/1` - Change job
|
|
- `max_stats/0` - Max all stats (GM)
|
|
|
|
## Example Usage
|
|
|
|
def start(cm) do
|
|
PlayerAPI.send_next(cm, "Hello there!")
|
|
end
|
|
|
|
def action(cm, mode, type, selection) do
|
|
if mode == 1 do
|
|
PlayerAPI.send_yes_no(cm, "Would you like to go to Henesys?")
|
|
else
|
|
PlayerAPI.dispose(cm)
|
|
end
|
|
end
|
|
"""
|
|
|
|
require Logger
|
|
|
|
alias Odinsea.Game.{Character, Inventory, Item, Map}
|
|
alias Odinsea.Channel.Packets
|
|
|
|
# Message type codes (matching Java implementation)
|
|
@msg_ok 0
|
|
@msg_next 0
|
|
@msg_prev 0
|
|
@msg_next_prev 0
|
|
@msg_yes_no 2
|
|
@msg_get_text 3
|
|
@msg_get_number 4
|
|
@msg_simple 5
|
|
@msg_accept_decline 0x0E
|
|
@msg_style 9
|
|
|
|
# ============================================================================
|
|
# Types
|
|
# ============================================================================
|
|
|
|
@type t :: %__MODULE__{
|
|
client_pid: pid(),
|
|
character_id: integer(),
|
|
npc_id: integer(),
|
|
quest_id: integer() | nil,
|
|
manager_pid: pid() | nil,
|
|
get_text: String.t() | nil
|
|
}
|
|
|
|
defstruct [
|
|
:client_pid,
|
|
:character_id,
|
|
:npc_id,
|
|
:quest_id,
|
|
:manager_pid,
|
|
:get_text
|
|
]
|
|
|
|
# ============================================================================
|
|
# Constructor
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Creates a new Player API instance.
|
|
|
|
## Parameters
|
|
- `client_pid` - Client process PID
|
|
- `character_id` - Character ID
|
|
- `npc_id` - NPC ID (or portal/reactor ID)
|
|
- `quest_id` - Quest ID (nil for non-quest)
|
|
- `manager_pid` - NPCManager PID (for disposal)
|
|
"""
|
|
@spec new(pid(), integer(), integer(), integer() | nil, pid() | nil) :: t()
|
|
def new(client_pid, character_id, npc_id, quest_id \\ nil, manager_pid \\ nil) do
|
|
%__MODULE__{
|
|
client_pid: client_pid,
|
|
character_id: character_id,
|
|
npc_id: npc_id,
|
|
quest_id: quest_id,
|
|
manager_pid: manager_pid,
|
|
get_text: nil
|
|
}
|
|
end
|
|
|
|
# ============================================================================
|
|
# Conversation Control
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Ends the conversation.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
"""
|
|
@spec dispose(t()) :: :ok
|
|
def dispose(%__MODULE__{manager_pid: nil}), do: :ok
|
|
def dispose(%__MODULE__{manager_pid: pid, client_pid: cpid, character_id: cid}) do
|
|
Odinsea.Scripting.NPCManager.dispose(cpid, cid)
|
|
end
|
|
|
|
@doc """
|
|
Schedules disposal on the next action.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
"""
|
|
@spec safe_dispose(t()) :: :ok
|
|
def safe_dispose(%__MODULE__{manager_pid: nil}), do: :ok
|
|
def safe_dispose(%__MODULE__{client_pid: cpid, character_id: cid}) do
|
|
Odinsea.Scripting.NPCManager.safe_dispose(cpid, cid)
|
|
end
|
|
|
|
@doc """
|
|
Sets the last message type for validation.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `msg_type` - Message type code
|
|
"""
|
|
@spec set_last_msg(t(), integer()) :: :ok
|
|
def set_last_msg(%__MODULE__{client_pid: cpid, character_id: cid}, msg_type) do
|
|
Odinsea.Scripting.NPCManager.set_last_msg(cpid, cid, msg_type)
|
|
end
|
|
|
|
# ============================================================================
|
|
# Basic Dialogs
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Sends an OK dialog.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `text` - Dialog text (can include #b#k tags)
|
|
"""
|
|
@spec send_ok(t(), String.t()) :: :ok
|
|
def send_ok(api, text) do
|
|
send_ok_npc(api, text, api.npc_id)
|
|
end
|
|
|
|
@doc """
|
|
Sends an OK dialog with specific NPC ID.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `text` - Dialog text
|
|
- `npc_id` - NPC ID to display
|
|
"""
|
|
@spec send_ok_npc(t(), String.t(), integer()) :: :ok
|
|
def send_ok_npc(api, text, npc_id) do
|
|
# TODO: Send NPCTalk packet
|
|
# Packet: LP_NPCTalk (opcode varies)
|
|
# Type: 0, text, "00 00"
|
|
|
|
# Placeholder: log and set last message
|
|
Logger.debug("NPC #{npc_id} says (OK): #{text}")
|
|
set_last_msg(api, @msg_ok)
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends a Next dialog (user clicks Next to continue).
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `text` - Dialog text
|
|
"""
|
|
@spec send_next(t(), String.t()) :: :ok
|
|
def send_next(api, text) do
|
|
send_next_npc(api, text, api.npc_id)
|
|
end
|
|
|
|
@doc """
|
|
Sends a Next dialog with specific NPC ID.
|
|
"""
|
|
@spec send_next_npc(t(), String.t(), integer()) :: :ok
|
|
def send_next_npc(api, text, npc_id) do
|
|
# Check for #L tags (would DC otherwise)
|
|
if String.contains?(text, "#L") do
|
|
send_simple_npc(api, text, npc_id)
|
|
else
|
|
# TODO: Send NPCTalk packet with "00 01" style
|
|
Logger.debug("NPC #{npc_id} says (Next): #{text}")
|
|
set_last_msg(api, @msg_next)
|
|
end
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends a Previous dialog.
|
|
"""
|
|
@spec send_prev(t(), String.t()) :: :ok
|
|
def send_prev(api, text) do
|
|
send_prev_npc(api, text, api.npc_id)
|
|
end
|
|
|
|
@doc """
|
|
Sends a Previous dialog with specific NPC ID.
|
|
"""
|
|
@spec send_prev_npc(t(), String.t(), integer()) :: :ok
|
|
def send_prev_npc(api, text, npc_id) do
|
|
if String.contains?(text, "#L") do
|
|
send_simple_npc(api, text, npc_id)
|
|
else
|
|
# TODO: Send NPCTalk packet with "01 00" style
|
|
Logger.debug("NPC #{npc_id} says (Prev): #{text}")
|
|
set_last_msg(api, @msg_prev)
|
|
end
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends a Next/Previous dialog.
|
|
"""
|
|
@spec send_next_prev(t(), String.t()) :: :ok
|
|
def send_next_prev(api, text) do
|
|
send_next_prev_npc(api, text, api.npc_id)
|
|
end
|
|
|
|
@doc """
|
|
Sends a Next/Previous dialog with specific NPC ID.
|
|
"""
|
|
@spec send_next_prev_npc(t(), String.t(), integer()) :: :ok
|
|
def send_next_prev_npc(api, text, npc_id) do
|
|
if String.contains?(text, "#L") do
|
|
send_simple_npc(api, text, npc_id)
|
|
else
|
|
# TODO: Send NPCTalk packet with "01 01" style
|
|
Logger.debug("NPC #{npc_id} says (Next/Prev): #{text}")
|
|
set_last_msg(api, @msg_next_prev)
|
|
end
|
|
:ok
|
|
end
|
|
|
|
# ============================================================================
|
|
# Speaker Dialogs (Player-to-NPC)
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Sends a Next dialog with speaker.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `text` - Dialog text
|
|
- `speaker_type` - Speaker type (0=NPC, 1=No ESC, 3=Player)
|
|
"""
|
|
@spec send_next_s(t(), String.t(), integer()) :: :ok
|
|
def send_next_s(api, text, speaker_type) do
|
|
send_next_s_npc(api, text, speaker_type, api.npc_id)
|
|
end
|
|
|
|
@doc """
|
|
Sends a Next dialog with speaker and specific NPC ID.
|
|
"""
|
|
@spec send_next_s_npc(t(), String.t(), integer(), integer()) :: :ok
|
|
def send_next_s_npc(api, text, speaker_type, npc_id) do
|
|
# TODO: Send NPCTalk with speaker
|
|
Logger.debug("NPC #{npc_id} says (NextS, type=#{speaker_type}): #{text}")
|
|
set_last_msg(api, @msg_next)
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends an OK dialog with speaker.
|
|
"""
|
|
@spec send_ok_s(t(), String.t(), integer()) :: :ok
|
|
def send_ok_s(api, text, speaker_type) do
|
|
# TODO: Send NPCTalk with speaker
|
|
Logger.debug("NPC #{api.npc_id} says (OkS, type=#{speaker_type}): #{text}")
|
|
set_last_msg(api, @msg_ok)
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends a Yes/No dialog with speaker.
|
|
"""
|
|
@spec send_yes_no_s(t(), String.t(), integer()) :: :ok
|
|
def send_yes_no_s(api, text, speaker_type) do
|
|
# TODO: Send NPCTalk with speaker
|
|
Logger.debug("NPC #{api.npc_id} asks (YesNoS, type=#{speaker_type}): #{text}")
|
|
set_last_msg(api, @msg_yes_no)
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends a Player-to-NPC dialog (convenience).
|
|
"""
|
|
@spec player_to_npc(t(), String.t()) :: :ok
|
|
def player_to_npc(api, text) do
|
|
send_next_s(api, text, 3)
|
|
end
|
|
|
|
# ============================================================================
|
|
# Choice Dialogs
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Sends a Yes/No dialog.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `text` - Question text
|
|
"""
|
|
@spec send_yes_no(t(), String.t()) :: :ok
|
|
def send_yes_no(api, text) do
|
|
send_yes_no_npc(api, text, api.npc_id)
|
|
end
|
|
|
|
@doc """
|
|
Sends a Yes/No dialog with specific NPC ID.
|
|
"""
|
|
@spec send_yes_no_npc(t(), String.t(), integer()) :: :ok
|
|
def send_yes_no_npc(api, text, npc_id) do
|
|
if String.contains?(text, "#L") do
|
|
send_simple_npc(api, text, npc_id)
|
|
else
|
|
# TODO: Send NPCTalk type 2
|
|
Logger.debug("NPC #{npc_id} asks (Yes/No): #{text}")
|
|
set_last_msg(api, @msg_yes_no)
|
|
end
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends an Accept/Decline dialog.
|
|
"""
|
|
@spec send_accept_decline(t(), String.t()) :: :ok
|
|
def send_accept_decline(api, text) do
|
|
send_accept_decline_npc(api, text, api.npc_id)
|
|
end
|
|
|
|
@doc """
|
|
Sends an Accept/Decline dialog with specific NPC ID.
|
|
"""
|
|
@spec send_accept_decline_npc(t(), String.t(), integer()) :: :ok
|
|
def send_accept_decline_npc(api, text, npc_id) do
|
|
if String.contains?(text, "#L") do
|
|
send_simple_npc(api, text, npc_id)
|
|
else
|
|
# TODO: Send NPCTalk type 0x0E/0x0F
|
|
Logger.debug("NPC #{npc_id} asks (Accept/Decline): #{text}")
|
|
set_last_msg(api, @msg_accept_decline)
|
|
end
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends a simple menu dialog.
|
|
|
|
Text should contain #L tags for menu items:
|
|
`#L0#Option 1#l\r\n#L1#Option 2#l`
|
|
"""
|
|
@spec send_simple(t(), String.t()) :: :ok
|
|
def send_simple(api, text) do
|
|
send_simple_npc(api, text, api.npc_id)
|
|
end
|
|
|
|
@doc """
|
|
Sends a simple menu dialog with specific NPC ID.
|
|
"""
|
|
@spec send_simple_npc(t(), String.t(), integer()) :: :ok
|
|
def send_simple_npc(api, text, npc_id) do
|
|
if not String.contains?(text, "#L") do
|
|
# Would DC otherwise
|
|
send_next_npc(api, text, npc_id)
|
|
else
|
|
# TODO: Send NPCTalk type 5
|
|
Logger.debug("NPC #{npc_id} menu: #{text}")
|
|
set_last_msg(api, @msg_simple)
|
|
end
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends a simple menu with selection array.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `text` - Intro text
|
|
- `selections` - List of menu options
|
|
"""
|
|
@spec send_simple_selections(t(), String.t(), [String.t()]) :: :ok
|
|
def send_simple_selections(api, text, selections) do
|
|
menu_text =
|
|
if length(selections) > 0 do
|
|
text <> "#b\r\n" <> build_menu(selections)
|
|
else
|
|
text
|
|
end
|
|
|
|
send_simple(api, menu_text)
|
|
end
|
|
|
|
defp build_menu(selections) do
|
|
selections
|
|
|> Enum.with_index()
|
|
|> Enum.map_join("\r\n", fn {item, idx} ->
|
|
"#L#{idx}##{item}#l"
|
|
end)
|
|
end
|
|
|
|
# ============================================================================
|
|
# Input Dialogs
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Sends a text input dialog.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `text` - Prompt text
|
|
"""
|
|
@spec send_get_text(t(), String.t()) :: :ok
|
|
def send_get_text(api, text) do
|
|
send_get_text_npc(api, text, api.npc_id)
|
|
end
|
|
|
|
@doc """
|
|
Sends a text input dialog with specific NPC ID.
|
|
"""
|
|
@spec send_get_text_npc(t(), String.t(), integer()) :: :ok
|
|
def send_get_text_npc(api, text, npc_id) do
|
|
if String.contains?(text, "#L") do
|
|
send_simple_npc(api, text, npc_id)
|
|
else
|
|
# TODO: Send NPCTalkText
|
|
Logger.debug("NPC #{npc_id} asks for text: #{text}")
|
|
set_last_msg(api, @msg_get_text)
|
|
end
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends a text input dialog with constraints.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `text` - Prompt text
|
|
- `min` - Minimum length
|
|
- `max` - Maximum length
|
|
- `default` - Default text
|
|
"""
|
|
@spec send_get_text_constrained(t(), String.t(), integer(), integer(), String.t()) :: :ok
|
|
def send_get_text_constrained(api, text, min, max, default) do
|
|
# TODO: Send NPCTalkText with constraints
|
|
Logger.debug("NPC #{api.npc_id} asks for text (#{min}-#{max}): #{text}")
|
|
set_last_msg(api, @msg_get_text)
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends a number input dialog.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `text` - Prompt text
|
|
- `default` - Default value
|
|
- `min` - Minimum value
|
|
- `max` - Maximum value
|
|
"""
|
|
@spec send_get_number(t(), String.t(), integer(), integer(), integer()) :: :ok
|
|
def send_get_number(api, text, default, min, max) do
|
|
if String.contains?(text, "#L") do
|
|
send_simple(api, text)
|
|
else
|
|
# TODO: Send NPCTalkNum
|
|
Logger.debug("NPC #{api.npc_id} asks for number (#{min}-#{max}, default #{default}): #{text}")
|
|
set_last_msg(api, @msg_get_number)
|
|
end
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends a style selection dialog (for hair/face).
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `text` - Prompt text
|
|
- `styles` - List of style IDs
|
|
"""
|
|
@spec send_style(t(), String.t(), [integer()]) :: :ok
|
|
def send_style(api, text, styles) do
|
|
send_style_paged(api, text, styles, 0)
|
|
end
|
|
|
|
@doc """
|
|
Sends a style selection dialog with page.
|
|
"""
|
|
@spec send_style_paged(t(), String.t(), [integer()], integer()) :: :ok
|
|
def send_style_paged(api, text, styles, page) do
|
|
# TODO: Send NPCTalkStyle
|
|
Logger.debug("NPC #{api.npc_id} style selection (page #{page}): #{length(styles)} options")
|
|
set_last_msg(api, @msg_style)
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends an avatar selection dialog.
|
|
"""
|
|
@spec ask_avatar(t(), String.t(), [integer()]) :: :ok
|
|
def ask_avatar(api, text, styles) do
|
|
send_style_paged(api, text, styles, 0)
|
|
end
|
|
|
|
@doc """
|
|
Sends a map selection dialog.
|
|
"""
|
|
@spec ask_map_selection(t(), String.t()) :: :ok
|
|
def ask_map_selection(api, selection_string) do
|
|
# TODO: Send MapSelection
|
|
Logger.debug("NPC #{api.npc_id} map selection")
|
|
set_last_msg(api, 0x10)
|
|
:ok
|
|
end
|
|
|
|
# ============================================================================
|
|
# Get/Set Text
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Sets the text received from player input.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `text` - The text value
|
|
"""
|
|
@spec set_get_text(t(), String.t()) :: t()
|
|
def set_get_text(%__MODULE__{} = api, text) do
|
|
%{api | get_text: text}
|
|
end
|
|
|
|
@doc """
|
|
Gets the text received from player input.
|
|
"""
|
|
@spec get_get_text(t()) :: String.t() | nil
|
|
def get_get_text(%__MODULE__{get_text: text}), do: text
|
|
|
|
# ============================================================================
|
|
# Character Appearance
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Sets the character's hair style.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `hair` - Hair style ID
|
|
"""
|
|
@spec set_hair(t(), integer()) :: :ok
|
|
def set_hair(api, hair) do
|
|
# TODO: Update character hair and send packet
|
|
Logger.debug("Set hair to #{hair}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sets the character's face.
|
|
"""
|
|
@spec set_face(t(), integer()) :: :ok
|
|
def set_face(api, face) do
|
|
Logger.debug("Set face to #{face}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sets the character's skin color.
|
|
"""
|
|
@spec set_skin(t(), integer()) :: :ok
|
|
def set_skin(api, color) do
|
|
Logger.debug("Set skin color to #{color}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sets a random avatar from given options.
|
|
"""
|
|
@spec set_random_avatar(t(), integer(), [integer()]) :: integer()
|
|
def set_random_avatar(api, ticket, options) do
|
|
if have_item(api, ticket) do
|
|
gain_item(api, ticket, -1)
|
|
style = Enum.random(options)
|
|
|
|
cond do
|
|
style < 100 -> set_skin(api, style)
|
|
style < 30000 -> set_face(api, style)
|
|
true -> set_hair(api, style)
|
|
end
|
|
|
|
1
|
|
else
|
|
-1
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Sets a specific avatar style.
|
|
"""
|
|
@spec set_avatar(t(), integer(), integer()) :: integer()
|
|
def set_avatar(api, ticket, style) do
|
|
if have_item(api, ticket) do
|
|
gain_item(api, ticket, -1)
|
|
|
|
cond do
|
|
style < 100 -> set_skin(api, style)
|
|
style < 30000 -> set_face(api, style)
|
|
true -> set_hair(api, style)
|
|
end
|
|
|
|
1
|
|
else
|
|
-1
|
|
end
|
|
end
|
|
|
|
# ============================================================================
|
|
# Warping
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Warps the player to a map.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `map_id` - Target map ID
|
|
"""
|
|
@spec warp(t(), integer()) :: :ok
|
|
def warp(api, map_id) do
|
|
# Use random portal
|
|
warp_portal(api, map_id, 0)
|
|
end
|
|
|
|
@doc """
|
|
Warps the player to a map with specific portal.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `map_id` - Target map ID
|
|
- `portal` - Portal ID or name
|
|
"""
|
|
@spec warp_portal(t(), integer(), integer() | String.t()) :: :ok
|
|
def warp_portal(api, map_id, portal) do
|
|
Logger.debug("Warping to map #{map_id}, portal #{inspect(portal)}")
|
|
# TODO: Send warp packet and handle map change
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Warps the player to an instanced map.
|
|
"""
|
|
@spec warp_instanced(t(), integer()) :: :ok
|
|
def warp_instanced(api, map_id) do
|
|
Logger.debug("Warping to instanced map #{map_id}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Warps all players on the current map.
|
|
"""
|
|
@spec warp_map(t(), integer(), integer()) :: :ok
|
|
def warp_map(api, map_id, portal) do
|
|
Logger.debug("Warping all players to map #{map_id}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Warps the entire party.
|
|
"""
|
|
@spec warp_party(t(), integer()) :: :ok
|
|
def warp_party(api, map_id) do
|
|
Logger.debug("Warping party to map #{map_id}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Plays the portal sound effect.
|
|
"""
|
|
@spec play_portal_se(t()) :: :ok
|
|
def play_portal_se(_api) do
|
|
# TODO: Send portal SE packet
|
|
:ok
|
|
end
|
|
|
|
# ============================================================================
|
|
# Items
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Gives or takes items from the player.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `item_id` - Item ID
|
|
- `quantity` - Positive to give, negative to take
|
|
"""
|
|
@spec gain_item(t(), integer(), integer()) :: :ok
|
|
def gain_item(api, item_id, quantity) do
|
|
gain_item_full(api, item_id, quantity, false, 0, -1, "")
|
|
end
|
|
|
|
@doc """
|
|
Gives items with random stats.
|
|
"""
|
|
@spec gain_item_random(t(), integer(), integer(), boolean()) :: :ok
|
|
def gain_item_random(api, item_id, quantity, random_stats) do
|
|
gain_item_full(api, item_id, quantity, random_stats, 0, -1, "")
|
|
end
|
|
|
|
@doc """
|
|
Gives items with slot bonus.
|
|
"""
|
|
@spec gain_item_slots(t(), integer(), integer(), boolean(), integer()) :: :ok
|
|
def gain_item_slots(api, item_id, quantity, random_stats, slots) do
|
|
gain_item_full(api, item_id, quantity, random_stats, 0, slots, "")
|
|
end
|
|
|
|
@doc """
|
|
Gives items with expiration period.
|
|
"""
|
|
@spec gain_item_period(t(), integer(), integer(), integer()) :: :ok
|
|
def gain_item_period(api, item_id, quantity, days) do
|
|
gain_item_full(api, item_id, quantity, false, days, -1, "")
|
|
end
|
|
|
|
@doc """
|
|
Gives items with full options.
|
|
"""
|
|
@spec gain_item_full(t(), integer(), integer(), boolean(), integer(), integer(), String.t()) :: :ok
|
|
def gain_item_full(api, item_id, quantity, random_stats, period, slots, owner) do
|
|
Logger.debug("Gain item #{item_id} x#{quantity} (random=#{random_stats}, period=#{period})")
|
|
# TODO: Add item to inventory
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Checks if player has an item.
|
|
"""
|
|
@spec have_item(t(), integer()) :: boolean()
|
|
def have_item(api, item_id) do
|
|
have_item_count(api, item_id, 1)
|
|
end
|
|
|
|
@doc """
|
|
Checks if player has at least quantity of an item.
|
|
"""
|
|
@spec have_item_count(t(), integer(), integer()) :: boolean()
|
|
def have_item_count(_api, _item_id, _quantity) do
|
|
# TODO: Check inventory
|
|
true
|
|
end
|
|
|
|
@doc """
|
|
Removes an item from inventory.
|
|
"""
|
|
@spec remove_item(t(), integer()) :: boolean()
|
|
def remove_item(api, item_id) do
|
|
# TODO: Remove item from inventory
|
|
Logger.debug("Remove item #{item_id}")
|
|
true
|
|
end
|
|
|
|
@doc """
|
|
Checks if player can hold an item.
|
|
"""
|
|
@spec can_hold(t(), integer()) :: boolean()
|
|
def can_hold(_api, _item_id) do
|
|
# TODO: Check inventory space
|
|
true
|
|
end
|
|
|
|
@doc """
|
|
Checks if player can hold quantity of an item.
|
|
"""
|
|
@spec can_hold_quantity(t(), integer(), integer()) :: boolean()
|
|
def can_hold_quantity(_api, _item_id, _quantity) do
|
|
# TODO: Check inventory space
|
|
true
|
|
end
|
|
|
|
# ============================================================================
|
|
# Meso/EXP
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Gives or takes meso.
|
|
|
|
## Parameters
|
|
- `api` - The API struct
|
|
- `amount` - Positive to give, negative to take
|
|
"""
|
|
@spec gain_meso(t(), integer()) :: :ok
|
|
def gain_meso(_api, amount) do
|
|
Logger.debug("Gain meso: #{amount}")
|
|
# TODO: Update meso
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Gets the player's current meso.
|
|
"""
|
|
@spec get_meso(t()) :: integer()
|
|
def get_meso(_api) do
|
|
# TODO: Get meso from character
|
|
0
|
|
end
|
|
|
|
@doc """
|
|
Gives EXP to the player.
|
|
"""
|
|
@spec gain_exp(t(), integer()) :: :ok
|
|
def gain_exp(_api, amount) do
|
|
Logger.debug("Gain EXP: #{amount}")
|
|
# TODO: Add EXP
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Gives EXP with rate multiplier.
|
|
"""
|
|
@spec gain_exp_r(t(), integer()) :: :ok
|
|
def gain_exp_r(api, amount) do
|
|
# TODO: Apply rate multiplier
|
|
gain_exp(api, amount)
|
|
end
|
|
|
|
# ============================================================================
|
|
# Jobs and Skills
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Changes the player's job.
|
|
"""
|
|
@spec change_job(t(), integer()) :: :ok
|
|
def change_job(_api, job_id) do
|
|
Logger.debug("Change job to #{job_id}")
|
|
# TODO: Change job and send packet
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Gets the player's current job.
|
|
"""
|
|
@spec get_job(t()) :: integer()
|
|
def get_job(_api) do
|
|
# TODO: Get job from character
|
|
0
|
|
end
|
|
|
|
@doc """
|
|
Teaches a skill to the player.
|
|
"""
|
|
@spec teach_skill(t(), integer(), integer(), integer()) :: :ok
|
|
def teach_skill(_api, skill_id, level, master_level) do
|
|
Logger.debug("Teach skill #{skill_id} level #{level}/#{master_level}")
|
|
# TODO: Add skill
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Teaches a skill with max master level.
|
|
"""
|
|
@spec teach_skill_max(t(), integer(), integer()) :: :ok
|
|
def teach_skill_max(api, skill_id, level) do
|
|
# TODO: Get max level from skill data
|
|
teach_skill(api, skill_id, level, 20)
|
|
end
|
|
|
|
@doc """
|
|
Checks if player has a skill.
|
|
"""
|
|
@spec has_skill(t(), integer()) :: boolean()
|
|
def has_skill(_api, _skill_id) do
|
|
# TODO: Check skills
|
|
false
|
|
end
|
|
|
|
@doc """
|
|
Maxes all skills for the player (GM).
|
|
"""
|
|
@spec max_all_skills(t()) :: :ok
|
|
def max_all_skills(_api) do
|
|
Logger.debug("Max all skills")
|
|
# TODO: Max all skills
|
|
:ok
|
|
end
|
|
|
|
# ============================================================================
|
|
# Stats
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Maxes all stats for the player (GM).
|
|
"""
|
|
@spec max_stats(t()) :: :ok
|
|
def max_stats(_api) do
|
|
Logger.debug("Max stats")
|
|
# TODO: Set all stats to max
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Adds AP (ability points).
|
|
"""
|
|
@spec gain_ap(t(), integer()) :: :ok
|
|
def gain_ap(_api, amount) do
|
|
Logger.debug("Gain AP: #{amount}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Resets stats to specified values.
|
|
"""
|
|
@spec reset_stats(t(), integer(), integer(), integer(), integer()) :: :ok
|
|
def reset_stats(_api, str, dex, int, luk) do
|
|
Logger.debug("Reset stats to STR=#{str} DEX=#{dex} INT=#{int} LUK=#{luk}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Gets a player stat by name.
|
|
|
|
Valid stat names: "LVL", "STR", "DEX", "INT", "LUK", "HP", "MP",
|
|
"MAXHP", "MAXMP", "RAP", "RSP", "GID", "GRANK", "ARANK", "GM", "ADMIN",
|
|
"GENDER", "FACE", "HAIR"
|
|
"""
|
|
@spec get_player_stat(t(), String.t()) :: integer()
|
|
def get_player_stat(_api, stat_name) do
|
|
Logger.debug("Get stat: #{stat_name}")
|
|
# TODO: Return stat value
|
|
case stat_name do
|
|
"LVL" -> 1
|
|
"GM" -> 0
|
|
"ADMIN" -> 0
|
|
_ -> 0
|
|
end
|
|
end
|
|
|
|
# ============================================================================
|
|
# Quests
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Starts a quest.
|
|
"""
|
|
@spec start_quest(t(), integer()) :: :ok
|
|
def start_quest(_api, quest_id) do
|
|
Logger.debug("Start quest #{quest_id}")
|
|
# TODO: Start quest
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Completes a quest.
|
|
"""
|
|
@spec complete_quest(t(), integer()) :: :ok
|
|
def complete_quest(_api, quest_id) do
|
|
Logger.debug("Complete quest #{quest_id}")
|
|
# TODO: Complete quest
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Forfeits a quest.
|
|
"""
|
|
@spec forfeit_quest(t(), integer()) :: :ok
|
|
def forfeit_quest(_api, quest_id) do
|
|
Logger.debug("Forfeit quest #{quest_id}")
|
|
# TODO: Forfeit quest
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Forces a quest start.
|
|
"""
|
|
@spec force_start_quest(t(), integer()) :: :ok
|
|
def force_start_quest(_api, quest_id) do
|
|
Logger.debug("Force start quest #{quest_id}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Forces a quest complete.
|
|
"""
|
|
@spec force_complete_quest(t(), integer()) :: :ok
|
|
def force_complete_quest(_api, quest_id) do
|
|
Logger.debug("Force complete quest #{quest_id}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Gets quest custom data.
|
|
"""
|
|
@spec get_quest_custom_data(t()) :: String.t() | nil
|
|
def get_quest_custom_data(_api) do
|
|
nil
|
|
end
|
|
|
|
@doc """
|
|
Sets quest custom data.
|
|
"""
|
|
@spec set_quest_custom_data(t(), String.t()) :: :ok
|
|
def set_quest_custom_data(_api, data) do
|
|
Logger.debug("Set quest custom data: #{data}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Gets quest record.
|
|
"""
|
|
@spec get_quest_record(t(), integer()) :: term()
|
|
def get_quest_record(_api, _quest_id) do
|
|
nil
|
|
end
|
|
|
|
@doc """
|
|
Gets quest status (0 = not started, 1 = in progress, 2 = completed).
|
|
"""
|
|
@spec get_quest_status(t(), integer()) :: integer()
|
|
def get_quest_status(_api, _quest_id) do
|
|
0
|
|
end
|
|
|
|
@doc """
|
|
Checks if quest is active.
|
|
"""
|
|
@spec is_quest_active(t(), integer()) :: boolean()
|
|
def is_quest_active(api, quest_id) do
|
|
get_quest_status(api, quest_id) == 1
|
|
end
|
|
|
|
@doc """
|
|
Checks if quest is finished.
|
|
"""
|
|
@spec is_quest_finished(t(), integer()) :: boolean()
|
|
def is_quest_finished(api, quest_id) do
|
|
get_quest_status(api, quest_id) == 2
|
|
end
|
|
|
|
# ============================================================================
|
|
# Map/Mob Operations
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Gets the current map ID.
|
|
"""
|
|
@spec get_map_id(t()) :: integer()
|
|
def get_map_id(_api) do
|
|
# TODO: Get current map
|
|
100000000
|
|
end
|
|
|
|
@doc """
|
|
Gets map reference.
|
|
"""
|
|
@spec get_map(t(), integer()) :: term()
|
|
def get_map(_api, map_id) do
|
|
# TODO: Get map instance
|
|
%{id: map_id}
|
|
end
|
|
|
|
@doc """
|
|
Spawns a monster.
|
|
"""
|
|
@spec spawn_monster(t(), integer()) :: :ok
|
|
def spawn_monster(api, mob_id) do
|
|
spawn_monster_qty(api, mob_id, 1)
|
|
end
|
|
|
|
@doc """
|
|
Spawns multiple monsters.
|
|
"""
|
|
@spec spawn_monster_qty(t(), integer(), integer()) :: :ok
|
|
def spawn_monster_qty(_api, mob_id, qty) do
|
|
Logger.debug("Spawn monster #{mob_id} x#{qty}")
|
|
# TODO: Spawn monsters
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Spawns monster at position.
|
|
"""
|
|
@spec spawn_monster_pos(t(), integer(), integer(), integer(), integer()) :: :ok
|
|
def spawn_monster_pos(_api, mob_id, qty, x, y) do
|
|
Logger.debug("Spawn monster #{mob_id} x#{qty} at (#{x}, #{y})")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Kills all monsters on current map.
|
|
"""
|
|
@spec kill_all_mob(t()) :: :ok
|
|
def kill_all_mob(_api) do
|
|
Logger.debug("Kill all monsters")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Kills specific monster.
|
|
"""
|
|
@spec kill_mob(t(), integer()) :: :ok
|
|
def kill_mob(_api, mob_id) do
|
|
Logger.debug("Kill monster #{mob_id}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Spawns an NPC.
|
|
"""
|
|
@spec spawn_npc(t(), integer()) :: :ok
|
|
def spawn_npc(api, npc_id) do
|
|
# TODO: Get player position and spawn
|
|
Logger.debug("Spawn NPC #{npc_id}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Spawns NPC at position.
|
|
"""
|
|
@spec spawn_npc_pos(t(), integer(), integer(), integer()) :: :ok
|
|
def spawn_npc_pos(_api, npc_id, x, y) do
|
|
Logger.debug("Spawn NPC #{npc_id} at (#{x}, #{y})")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Removes an NPC from current map.
|
|
"""
|
|
@spec remove_npc(t(), integer()) :: :ok
|
|
def remove_npc(_api, npc_id) do
|
|
Logger.debug("Remove NPC #{npc_id}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Resets a map.
|
|
"""
|
|
@spec reset_map(t(), integer()) :: :ok
|
|
def reset_map(_api, map_id) do
|
|
Logger.debug("Reset map #{map_id}")
|
|
# TODO: Reset map
|
|
:ok
|
|
end
|
|
|
|
# ============================================================================
|
|
# Party Operations
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Checks if player is party leader.
|
|
"""
|
|
@spec is_leader(t()) :: boolean()
|
|
def is_leader(_api) do
|
|
# TODO: Check party leadership
|
|
false
|
|
end
|
|
|
|
@doc """
|
|
Gets party members in current map.
|
|
"""
|
|
@spec party_members_in_map(t()) :: integer()
|
|
def party_members_in_map(_api) do
|
|
# TODO: Count party members in map
|
|
1
|
|
end
|
|
|
|
@doc """
|
|
Gets all party members.
|
|
"""
|
|
@spec get_party_members(t()) :: [term()]
|
|
def get_party_members(_api) do
|
|
[]
|
|
end
|
|
|
|
@doc """
|
|
Checks if all party members are in current map.
|
|
"""
|
|
@spec all_members_here(t()) :: boolean()
|
|
def all_members_here(_api) do
|
|
true
|
|
end
|
|
|
|
@doc """
|
|
Warps party with EXP reward.
|
|
"""
|
|
@spec warp_party_with_exp(t(), integer(), integer()) :: :ok
|
|
def warp_party_with_exp(api, map_id, exp) do
|
|
warp_party(api, map_id)
|
|
gain_exp(api, exp)
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Warps party with EXP and meso reward.
|
|
"""
|
|
@spec warp_party_with_exp_meso(t(), integer(), integer(), integer()) :: :ok
|
|
def warp_party_with_exp_meso(api, map_id, exp, meso) do
|
|
warp_party(api, map_id)
|
|
gain_exp(api, exp)
|
|
gain_meso(api, meso)
|
|
:ok
|
|
end
|
|
|
|
# ============================================================================
|
|
# Guild Operations
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Gets guild ID.
|
|
"""
|
|
@spec get_guild_id(t()) :: integer()
|
|
def get_guild_id(_api) do
|
|
0
|
|
end
|
|
|
|
@doc """
|
|
Increases guild capacity.
|
|
"""
|
|
@spec increase_guild_capacity(t(), boolean()) :: boolean()
|
|
def increase_guild_capacity(_api, _true_max) do
|
|
false
|
|
end
|
|
|
|
@doc """
|
|
Displays guild ranks.
|
|
"""
|
|
@spec display_guild_ranks(t()) :: :ok
|
|
def display_guild_ranks(_api) do
|
|
:ok
|
|
end
|
|
|
|
# ============================================================================
|
|
# Messages
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Sends a message to the player.
|
|
"""
|
|
@spec player_message(t(), String.t()) :: :ok
|
|
def player_message(api, message) do
|
|
player_message_type(api, 5, message)
|
|
end
|
|
|
|
@doc """
|
|
Sends a message with type.
|
|
|
|
Types: 1 = Popup, 5 = Chat, -1 = Important
|
|
"""
|
|
@spec player_message_type(t(), integer(), String.t()) :: :ok
|
|
def player_message_type(_api, type, message) do
|
|
Logger.debug("Player message (#{type}): #{message}")
|
|
# TODO: Send message packet
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends a message to the map.
|
|
"""
|
|
@spec map_message(t(), String.t()) :: :ok
|
|
def map_message(api, message) do
|
|
map_message_type(api, 5, message)
|
|
end
|
|
|
|
@doc """
|
|
Sends a message to the map with type.
|
|
"""
|
|
@spec map_message_type(t(), integer(), String.t()) :: :ok
|
|
def map_message_type(_api, type, message) do
|
|
Logger.debug("Map message (#{type}): #{message}")
|
|
# TODO: Broadcast message
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends a world message.
|
|
"""
|
|
@spec world_message(t(), integer(), String.t()) :: :ok
|
|
def world_message(_api, type, message) do
|
|
Logger.debug("World message (#{type}): #{message}")
|
|
# TODO: Broadcast to world
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Sends a guild message.
|
|
"""
|
|
@spec guild_message(t(), String.t()) :: :ok
|
|
def guild_message(_api, message) do
|
|
Logger.debug("Guild message: #{message}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Shows quest message.
|
|
"""
|
|
@spec show_quest_msg(t(), String.t()) :: :ok
|
|
def show_quest_msg(_api, msg) do
|
|
Logger.debug("Quest message: #{msg}")
|
|
:ok
|
|
end
|
|
|
|
# ============================================================================
|
|
# Storage/Shop
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Opens storage.
|
|
"""
|
|
@spec open_storage(t()) :: :ok
|
|
def open_storage(_api) do
|
|
Logger.debug("Open storage")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Opens a shop.
|
|
"""
|
|
@spec open_shop(t(), integer()) :: :ok
|
|
def open_shop(_api, shop_id) do
|
|
Logger.debug("Open shop #{shop_id}")
|
|
:ok
|
|
end
|
|
|
|
# ============================================================================
|
|
# Event/Instance
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Gets event manager.
|
|
"""
|
|
@spec get_event_manager(t(), String.t()) :: term()
|
|
def get_event_manager(_api, _event_name) do
|
|
nil
|
|
end
|
|
|
|
@doc """
|
|
Gets event instance.
|
|
"""
|
|
@spec get_event_instance(t()) :: term()
|
|
def get_event_instance(_api) do
|
|
nil
|
|
end
|
|
|
|
@doc """
|
|
Removes player from instance.
|
|
"""
|
|
@spec remove_player_from_instance(t()) :: boolean()
|
|
def remove_player_from_instance(_api) do
|
|
false
|
|
end
|
|
|
|
@doc """
|
|
Checks if player is in an instance.
|
|
"""
|
|
@spec is_player_instance(t()) :: boolean()
|
|
def is_player_instance(_api) do
|
|
false
|
|
end
|
|
|
|
# ============================================================================
|
|
# Miscellaneous
|
|
# ============================================================================
|
|
|
|
@doc """
|
|
Opens an NPC by ID.
|
|
"""
|
|
@spec open_npc(t(), integer()) :: :ok
|
|
def open_npc(%__MODULE__{client_pid: cpid, character_id: cid}, npc_id) do
|
|
Odinsea.Scripting.NPCManager.start_conversation(cpid, cid, npc_id)
|
|
end
|
|
|
|
@doc """
|
|
Opens an NPC with specific script.
|
|
"""
|
|
@spec open_npc_script(t(), integer(), String.t()) :: :ok
|
|
def open_npc_script(%__MODULE__{client_pid: cpid, character_id: cid}, npc_id, script_name) do
|
|
Odinsea.Scripting.NPCManager.start_conversation(cpid, cid, npc_id, script_name: script_name)
|
|
end
|
|
|
|
@doc """
|
|
Gets player name.
|
|
"""
|
|
@spec get_name(t()) :: String.t()
|
|
def get_name(_api) do
|
|
"Unknown"
|
|
end
|
|
|
|
@doc """
|
|
Gets channel number.
|
|
"""
|
|
@spec get_channel(t()) :: integer()
|
|
def get_channel(_api) do
|
|
1
|
|
end
|
|
|
|
@doc """
|
|
Adds HP.
|
|
"""
|
|
@spec add_hp(t(), integer()) :: :ok
|
|
def add_hp(_api, amount) do
|
|
Logger.debug("Add HP: #{amount}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Shows an effect.
|
|
"""
|
|
@spec show_effect(t(), boolean(), String.t()) :: :ok
|
|
def show_effect(_api, _broadcast, effect) do
|
|
Logger.debug("Show effect: #{effect}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Plays a sound.
|
|
"""
|
|
@spec play_sound(t(), boolean(), String.t()) :: :ok
|
|
def play_sound(_api, _broadcast, sound) do
|
|
Logger.debug("Play sound: #{sound}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Changes background music.
|
|
"""
|
|
@spec change_music(t(), String.t()) :: :ok
|
|
def change_music(_api, song_name) do
|
|
Logger.debug("Change music: #{song_name}")
|
|
:ok
|
|
end
|
|
|
|
@doc """
|
|
Gains NX (cash points).
|
|
"""
|
|
@spec gain_nx(t(), integer()) :: :ok
|
|
def gain_nx(_api, amount) do
|
|
Logger.debug("Gain NX: #{amount}")
|
|
:ok
|
|
end
|
|
end
|