defmodule Odinsea.Constants.Game do @moduledoc """ Game constants ported from Java GameConstants. These define gameplay mechanics, limits, and rates. """ # Character limits @max_level 250 @max_ap 999 @max_hp_mp 999_999 @base_max_hp 50 @base_max_mp 50 # Inventory limits @max_inventory_slots 128 @equip_slots 96 @use_slots 96 @setup_slots 96 @etc_slots 96 @cash_slots 96 # Meso limits @max_meso 9_999_999_999 @max_storage_meso 9_999_999_999 # Guild limits @max_guild_name_length 12 @max_guild_members 100 # Party limits @max_party_members 6 @max_expedition_members 30 # GMS specific flag @gms true @doc """ Returns the maximum character level. """ def max_level, do: @max_level @doc """ Returns the maximum AP. """ def max_ap, do: @max_ap @doc """ Returns the maximum HP/MP. """ def max_hp_mp, do: @max_hp_mp @doc """ Returns the base max HP for new characters. """ def base_max_hp, do: @base_max_hp @doc """ Returns the base max MP for new characters. """ def base_max_mp, do: @base_max_mp @doc """ Returns the max inventory slots per type. """ def max_inventory_slots, do: @max_inventory_slots def equip_slots, do: @equip_slots def use_slots, do: @use_slots def setup_slots, do: @setup_slots def etc_slots, do: @etc_slots def cash_slots, do: @cash_slots @doc """ Returns the max meso a character can hold. """ def max_meso, do: @max_meso @doc """ Returns the max meso in storage. """ def max_storage_meso, do: @max_storage_meso @doc """ Returns true if this is a GMS server. """ def gms?, do: @gms @doc """ Returns the rates from configuration. """ def rates do Application.get_env(:odinsea, :rates, []) end @doc """ Returns the EXP rate. """ def exp_rate do rates()[:exp] || 1 end @doc """ Returns the meso rate. """ def meso_rate do rates()[:meso] || 1 end @doc """ Returns the drop rate. """ def drop_rate do rates()[:drop] || 1 end # Job classification helpers @doc """ Returns true if the job is a beginner job. """ def beginner?(job), do: div(job, 1000) == 0 && rem(job, 100) == 0 @doc """ Returns true if the job is a warrior class. """ def warrior?(job), do: div(job, 100) == 1 @doc """ Returns true if the job is a magician class. """ def magician?(job), do: div(job, 100) == 2 @doc """ Returns true if the job is a bowman class. """ def bowman?(job), do: div(job, 100) == 3 @doc """ Returns true if the job is a thief class. """ def thief?(job), do: div(job, 100) == 4 @doc """ Returns true if the job is a pirate class. """ def pirate?(job), do: div(job, 100) == 5 || div(job, 100) == 51 || div(job, 100) == 52 @doc """ Returns true if the job is a resistance class. """ def resistance?(job), do: div(job, 1000) == 3 @doc """ Returns true if the job is a cygnus class. """ def cygnus?(job), do: div(job, 1000) == 1 @doc """ Returns true if the job is an aran. """ def aran?(job), do: div(job, 100) == 21 @doc """ Returns true if the job is an evan. """ def evan?(job), do: div(job, 100) == 22 || job == 2001 @doc """ Returns the job name for a given job ID. """ def job_name(job) do case job do 0 -> "Beginner" 100 -> "Warrior" 110 -> "Fighter" 120 -> "Page" 130 -> "Spearman" 111 -> "Crusader" 121 -> "Knight" 131 -> "Dragon Knight" 112 -> "Hero" 122 -> "Paladin" 132 -> "Dark Knight" 200 -> "Magician" 210 -> "Wizard (F/P)" 220 -> "Wizard (I/L)" 230 -> "Cleric" 211 -> "Mage (F/P)" 221 -> "Mage (I/L)" 231 -> "Bishop" 212 -> "Arch Mage (F/P)" 222 -> "Arch Mage (I/L)" 232 -> "Arch Mage" 300 -> "Bowman" 310 -> "Hunter" 320 -> "Crossbowman" 311 -> "Ranger" 321 -> "Sniper" 312 -> "Bowmaster" 322 -> "Marksman" 400 -> "Thief" 410 -> "Assassin" 420 -> "Bandit" 411 -> "Hermit" 421 -> "Chief Bandit" 412 -> "Night Lord" 422 -> "Shadower" 500 -> "Pirate" 510 -> "Brawler" 520 -> "Gunslinger" 511 -> "Marauder" 521 -> "Outlaw" 512 -> "Buccaneer" 522 -> "Corsair" 1000 -> "Noblesse" 1100 -> "Dawn Warrior" 1200 -> "Blaze Wizard" 1300 -> "Wind Archer" 1400 -> "Night Walker" 1500 -> "Thunder Breaker" 2000 -> "Legend" 2100 -> "Aran" 2001 -> "Evan" 2002 -> "Mercedes" _ -> "Unknown" end end end