Files
odinsea-elixir/lib/odinsea/game/events.ex
2026-02-14 23:12:33 -07:00

179 lines
4.1 KiB
Elixir

defmodule Odinsea.Game.Events do
@moduledoc """
Event type definitions and map IDs.
Ported from Java `server.events.MapleEventType`.
Each event type has associated map IDs where the event takes place.
"""
@typedoc "Event type atom"
@type t :: :coconut | :coke_play | :fitness | :ola_ola | :ox_quiz | :survival | :snowball
# ============================================================================
# Event Map IDs
# ============================================================================
@event_maps %{
# Coconut event - team-based coconut hitting
coconut: [109080000],
# Coke Play event (similar to coconut)
coke_play: [109080010],
# Fitness event - 4 stage obstacle course
fitness: [109040000, 109040001, 109040002, 109040003, 109040004],
# Ola Ola event - 3 stage portal guessing game
ola_ola: [109030001, 109030002, 109030003],
# OX Quiz event - True/False quiz
ox_quiz: [109020001],
# Survival event - Last man standing (2 maps)
survival: [809040000, 809040100],
# Snowball event - Team snowball rolling competition
snowball: [109060000]
}
@doc """
Returns all event types.
"""
def all do
Map.keys(@event_maps)
end
@doc """
Returns the map IDs for a given event type.
## Examples
iex> Odinsea.Game.Events.map_ids(:coconut)
[109080000]
iex> Odinsea.Game.Events.map_ids(:fitness)
[109040000, 109040001, 109040002, 109040003, 109040004]
"""
def map_ids(event_type) do
Map.get(@event_maps, event_type, [])
end
@doc """
Returns the entry map ID (first map) for an event type.
"""
def entry_map_id(event_type) do
case map_ids(event_type) do
[first | _] -> first
[] -> nil
end
end
@doc """
Gets an event type by string name (case-insensitive).
## Examples
iex> Odinsea.Game.Events.get_by_string("coconut")
:coconut
iex> Odinsea.Game.Events.get_by_string("OX_QUIZ")
:ox_quiz
iex> Odinsea.Game.Events.get_by_string("invalid")
nil
"""
def get_by_string(str) when is_binary(str) do
str = String.downcase(str)
Enum.find(all(), fn type ->
Atom.to_string(type) == str or
String.replace(Atom.to_string(type), "_", "") == str
end)
end
def get_by_string(_), do: nil
@doc """
Returns a human-readable name for the event type.
## Examples
iex> Odinsea.Game.Events.display_name(:coconut)
"Coconut"
iex> Odinsea.Game.Events.display_name(:ola_ola)
"Ola Ola"
"""
def display_name(event_type) do
event_type
|> Atom.to_string()
|> String.replace("_", " ")
|> String.split()
|> Enum.map(&String.capitalize/1)
|> Enum.join(" ")
end
@doc """
Returns the number of stages/maps for an event.
"""
def stage_count(event_type) do
length(map_ids(event_type))
end
@doc """
Checks if a map ID belongs to any event.
Returns the event type if found, nil otherwise.
"""
def event_for_map(map_id) when is_integer(map_id) do
Enum.find(all(), fn type ->
map_id in map_ids(type)
end)
end
def event_for_map(_), do: nil
@doc """
Checks if a map ID is the finish map (109050000).
"""
def finish_map?(109050000), do: true
def finish_map?(_), do: false
@doc """
Returns true if the event is a race-type event (timed).
"""
def race_event?(:fitness), do: true
def race_event?(:ola_ola), do: true
def race_event?(:survival), do: true
def race_event?(_), do: false
@doc """
Returns true if the event is team-based.
"""
def team_event?(:coconut), do: true
def team_event?(:snowball), do: true
def team_event?(_), do: false
@doc """
Returns true if the event has multiple stages.
"""
def multi_stage?(event_type) do
stage_count(event_type) > 1
end
@doc """
Returns the stage index for a map ID within an event.
Returns 0-based index or nil if not part of event.
"""
def stage_index(event_type, map_id) do
map_ids(event_type)
|> Enum.find_index(&(&1 == map_id))
end
@doc """
Returns all event data as a map.
"""
def all_event_data do
@event_maps
end
end