defmodule Odinsea.Database.Schema.InventoryItem do @moduledoc """ Ecto schema for the inventoryitems table. Stores all items for all characters. """ use Ecto.Schema import Ecto.Changeset @primary_key {:inventoryitemid, :integer, autogenerate: false} schema "inventoryitems" do field :characterid, :integer field :itemid, :integer field :inventorytype, :integer field :position, :integer field :quantity, :integer field :owner, :string, default: "" field :petid, :integer, default: -1 field :flag, :integer, default: 0 field :expiration, :integer, default: -1 field :gift_from, :string, source: :giftFrom, default: "" field :uniqueid, :integer, default: -1 # Equipment-specific fields (stored in the same table) field :upgradeslots, :integer, default: 0 field :level, :integer, default: 0 field :str, :integer, default: 0 field :dex, :integer, default: 0 field :int, :integer, default: 0 field :luk, :integer, default: 0 field :hp, :integer, default: 0 field :mp, :integer, default: 0 field :watk, :integer, default: 0 field :matk, :integer, default: 0 field :wdef, :integer, default: 0 field :mdef, :integer, default: 0 field :acc, :integer, default: 0 field :avoid, :integer, default: 0 field :hands, :integer, default: 0 field :speed, :integer, default: 0 field :jump, :integer, default: 0 field :locked, :integer, default: 0 field :vicioushammer, :integer, default: 0 field :itemexp, :integer, default: 0 field :durability, :integer, default: -1 field :enhance, :integer, default: 0 field :potential1, :integer, default: 0 field :potential2, :integer, default: 0 field :potential3, :integer, default: 0 field :hp_r, :integer, source: :hpR, default: 0 field :mp_r, :integer, source: :mpR, default: 0 field :incskill, :integer, default: -1 field :charmexp, :integer, default: -1 field :pvpdamage, :integer, default: 0 end @doc """ Changeset for creating a new inventory item. """ def changeset(item, attrs) do item |> cast(attrs, [ :inventoryitemid, :characterid, :itemid, :inventorytype, :position, :quantity, :owner, :petid, :flag, :expiration, :gift_from, :uniqueid, :upgradeslots, :level, :str, :dex, :int, :luk, :hp, :mp, :watk, :matk, :wdef, :mdef, :acc, :avoid, :hands, :speed, :jump, :vicioushammer, :itemexp, :durability, :enhance, :potential1, :potential2, :potential3, :hp_r, :mp_r, :incskill, :charmexp, :pvpdamage ]) |> validate_required([:characterid, :itemid, :inventorytype, :position, :quantity]) end @doc """ Converts a database item to a game Item or Equip struct. """ def to_game_item(%__MODULE__{} = db_item) do base_fields = %{ id: db_item.inventoryitemid, item_id: db_item.itemid, position: db_item.position, quantity: db_item.quantity, flag: db_item.flag, unique_id: db_item.uniqueid, expiration: db_item.expiration, owner: db_item.owner || "", gift_from: db_item.gift_from || "", gm_log: "", inventory_id: db_item.inventoryitemid, pet: nil } if is_equip?(db_item) do struct(Odinsea.Game.Equip, Map.merge(base_fields, equip_fields(db_item))) else struct(Odinsea.Game.Item, base_fields) end end defp is_equip?(db_item) do # Equipment items have inventory type 1 (EQUIP) or -1 (EQUIPPED) # or have non-zero equip stats db_item.inventorytype in [1, -1] or db_item.upgradeslots > 0 or db_item.str > 0 or db_item.dex > 0 or db_item.int > 0 or db_item.luk > 0 or db_item.watk > 0 or db_item.wdef > 0 end defp equip_fields(db_item) do %{ upgrade_slots: db_item.upgradeslots, level: db_item.level, vicious_hammer: db_item.vicioushammer, enhance: db_item.enhance, str: db_item.str, dex: db_item.dex, int: db_item.int, luk: db_item.luk, hp: db_item.hp, mp: db_item.mp, watk: db_item.watk, matk: db_item.matk, wdef: db_item.wdef, mdef: db_item.mdef, acc: db_item.acc, avoid: db_item.avoid, hands: db_item.hands, speed: db_item.speed, jump: db_item.jump, hp_r: db_item.hp_r, mp_r: db_item.mp_r, charm_exp: db_item.charmexp, pvp_damage: db_item.pvpdamage, item_exp: db_item.itemexp, durability: db_item.durability, inc_skill: db_item.incskill, potential1: db_item.potential1, potential2: db_item.potential2, potential3: db_item.potential3, ring: nil, android: nil } end @doc """ Converts a game Item or Equip to database attributes. """ def from_game_item(%Odinsea.Game.Item{} = item, character_id, inv_type) do %{ inventoryitemid: item.id, characterid: character_id, itemid: item.item_id, inventorytype: Odinsea.Game.InventoryType.type_value(inv_type), position: item.position, quantity: item.quantity, owner: item.owner, petid: if(item.pet, do: item.pet.unique_id, else: -1), flag: item.flag, expiration: item.expiration, gift_from: item.gift_from, uniqueid: item.unique_id } end def from_game_item(%Odinsea.Game.Equip{} = equip, character_id, inv_type) do base = from_game_item(%Odinsea.Game.Item{} = equip, character_id, inv_type) Map.merge(base, %{ upgradeslots: equip.upgrade_slots, level: equip.level, str: equip.str, dex: equip.dex, int: equip.int, luk: equip.luk, hp: equip.hp, mp: equip.mp, watk: equip.watk, matk: equip.matk, wdef: equip.wdef, mdef: equip.mdef, acc: equip.acc, avoid: equip.avoid, hands: equip.hands, speed: equip.speed, jump: equip.jump, vicioushammer: equip.vicious_hammer, itemexp: equip.item_exp, durability: equip.durability, enhance: equip.enhance, potential1: equip.potential1, potential2: equip.potential2, potential3: equip.potential3, hp_r: equip.hp_r, mp_r: equip.mp_r, incskill: equip.inc_skill, charmexp: equip.charm_exp, pvpdamage: equip.pvp_damage }) end end