defmodule Odinsea.Game.Item do @moduledoc """ Represents an item in the game. Items can be regular stackable items or equipment with stats. """ @type t :: %__MODULE__{ id: integer(), item_id: integer(), position: integer(), quantity: integer(), flag: integer(), unique_id: integer(), expiration: integer(), owner: String.t(), gift_from: String.t(), gm_log: String.t(), inventory_id: integer(), pet: map() | nil } defstruct [ :id, :item_id, :position, :quantity, :flag, :unique_id, :expiration, :owner, :gift_from, :gm_log, :inventory_id, :pet ] @doc """ Creates a new item. """ def new(item_id, position, quantity, flag \\ 0, unique_id \\ -1) do %__MODULE__{ id: nil, item_id: item_id, position: position, quantity: quantity, flag: flag, unique_id: unique_id, expiration: -1, owner: "", gift_from: "", gm_log: "", inventory_id: 0, pet: nil } end @doc """ Creates a copy of an item. """ def copy(%__MODULE__{} = item) do %{item | id: nil} end @doc """ Returns the type of item (2 = regular item). """ def type(%__MODULE__{}), do: 2 @doc """ Checks if two items can be stacked (same item_id, owner, expiration). """ def stackable?(%__MODULE__{} = item1, %__MODULE__{} = item2) do item1.item_id == item2.item_id && item1.owner == item2.owner && item1.expiration == item2.expiration && item1.flag == item2.flag end @doc """ Compares items by position for sorting. """ def compare(%__MODULE__{} = item1, %__MODULE__{} = item2) do pos1 = abs(item1.position) pos2 = abs(item2.position) cond do pos1 < pos2 -> :lt pos1 == pos2 -> :eq true -> :gt end end end defmodule Odinsea.Game.Equip do @moduledoc """ Represents an equipment item with stats. Extends the base Item with equipment-specific fields. """ @type t :: %__MODULE__{ # Base item fields id: integer(), item_id: integer(), position: integer(), quantity: integer(), flag: integer(), unique_id: integer(), expiration: integer(), owner: String.t(), gift_from: String.t(), gm_log: String.t(), inventory_id: integer(), pet: map() | nil, # Equipment-specific fields upgrade_slots: integer(), level: integer(), vicious_hammer: integer(), enhance: integer(), str: integer(), dex: integer(), int: integer(), luk: integer(), hp: integer(), mp: integer(), watk: integer(), matk: integer(), wdef: integer(), mdef: integer(), acc: integer(), avoid: integer(), hands: integer(), speed: integer(), jump: integer(), hp_r: integer(), mp_r: integer(), charm_exp: integer(), pvp_damage: integer(), item_exp: integer(), durability: integer(), inc_skill: integer(), potential1: integer(), potential2: integer(), potential3: integer(), ring: map() | nil, android: map() | nil } defstruct [ # Base item fields :id, :item_id, :position, :quantity, :flag, :unique_id, :expiration, :owner, :gift_from, :gm_log, :inventory_id, :pet, # Equipment-specific fields :upgrade_slots, :level, :vicious_hammer, :enhance, :str, :dex, :int, :luk, :hp, :mp, :watk, :matk, :wdef, :mdef, :acc, :avoid, :hands, :speed, :jump, :hp_r, :mp_r, :charm_exp, :pvp_damage, :item_exp, :durability, :inc_skill, :potential1, :potential2, :potential3, :ring, :android ] @armor_ratio 350_000 @weapon_ratio 700_000 @doc """ Creates a new equipment item. """ def new(item_id, position, flag \\ 0, unique_id \\ -1) do %__MODULE__{ id: nil, item_id: item_id, position: position, quantity: 1, flag: flag, unique_id: unique_id, expiration: -1, owner: "", gift_from: "", gm_log: "", inventory_id: 0, pet: nil, upgrade_slots: 0, level: 0, vicious_hammer: 0, enhance: 0, str: 0, dex: 0, int: 0, luk: 0, hp: 0, mp: 0, watk: 0, matk: 0, wdef: 0, mdef: 0, acc: 0, avoid: 0, hands: 0, speed: 0, jump: 0, hp_r: 0, mp_r: 0, charm_exp: -1, pvp_damage: 0, item_exp: 0, durability: -1, inc_skill: -1, potential1: 0, potential2: 0, potential3: 0, ring: nil, android: nil } end @doc """ Returns the type of item (1 = equipment). """ def type(%__MODULE__{}), do: 1 @doc """ Gets the potential state of the equipment. Returns: 0=none, 5=rare, 6=epic, 7=unique, 8=legendary """ def potential_state(%__MODULE__{} = equip) do pots = equip.potential1 + equip.potential2 + equip.potential3 cond do equip.potential1 >= 40_000 or equip.potential2 >= 40_000 or equip.potential3 >= 40_000 -> 8 equip.potential1 >= 30_000 or equip.potential2 >= 30_000 or equip.potential3 >= 30_000 -> 7 equip.potential1 >= 20_000 or equip.potential2 >= 20_000 or equip.potential3 >= 20_000 -> 6 pots >= 1 -> 5 pots < 0 -> 1 true -> 0 end end @doc """ Gets the equipment level based on item EXP. """ def equip_level(%__MODULE__{} = equip) do if equip.item_exp <= 0 do base_level(equip) else calculate_equip_level(equip, base_level(equip), equip_exp(equip)) end end defp calculate_equip_level(equip, level, exp) do # Simplified - would need item data to check max level max_level = 10 if level >= max_level or exp <= 0 do level else # Simplified exp calculation needed_exp = level * 100 if exp >= needed_exp do calculate_equip_level(equip, level + 1, exp - needed_exp) else level end end end defp base_level(_equip), do: 1 @doc """ Gets the equipment EXP value. """ def equip_exp(%__MODULE__{} = equip) do if equip.item_exp <= 0 do 0 else # Simplified ratio div(equip.item_exp, @armor_ratio) end end @doc """ Creates a copy of an equipment. """ def copy(%__MODULE__{} = equip) do %{equip | id: nil} end end