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

113 lines
2.6 KiB
Elixir

defmodule Odinsea.Game.ShopItem do
@moduledoc """
Represents an item listed in a player shop or hired merchant.
Ported from src/server/shops/MaplePlayerShopItem.java
Each shop item contains:
- The actual item data
- Number of bundles (how many stacks)
- Price per bundle
"""
alias Odinsea.Game.{Item, Equip}
@type t :: %__MODULE__{
item: Item.t() | Equip.t(),
bundles: integer(),
price: integer()
}
defstruct [
:item,
:bundles,
:price
]
@doc """
Creates a new shop item.
"""
def new(item, bundles, price) do
%__MODULE__{
item: item,
bundles: bundles,
price: price
}
end
@doc """
Calculates the total quantity available (bundles * quantity per bundle).
"""
def total_quantity(%__MODULE__{} = shop_item) do
per_bundle = shop_item.item.quantity
shop_item.bundles * per_bundle
end
@doc """
Calculates the total price for a given quantity.
"""
def calculate_price(%__MODULE__{} = shop_item, quantity) do
shop_item.price * quantity
end
@doc """
Reduces the number of bundles by the given quantity.
Returns the updated shop item.
"""
def reduce_bundles(%__MODULE__{} = shop_item, quantity) do
%{shop_item | bundles: shop_item.bundles - quantity}
end
@doc """
Checks if the item is sold out (no bundles remaining).
"""
def sold_out?(%__MODULE__{} = shop_item) do
shop_item.bundles <= 0
end
@doc """
Creates a copy of the item for the buyer.
The copy has the quantity adjusted based on bundles purchased.
"""
def create_buyer_item(%__MODULE__{} = shop_item, quantity) do
item_copy = copy_item(shop_item.item)
per_bundle = shop_item.item.quantity
total_qty = quantity * per_bundle
case item_copy do
%{quantity: _} = item ->
%{item | quantity: total_qty}
equip ->
# Equipment doesn't have quantity field
equip
end
end
defp copy_item(%Item{} = item), do: Item.copy(item)
defp copy_item(%Equip{} = equip), do: Equip.copy(equip)
defp copy_item(item), do: item
@doc """
Removes karma flags from an item (for trade).
"""
def remove_karma(%__MODULE__{} = shop_item) do
item = shop_item.item
updated_item =
cond do
# KARMA_EQ flag = 0x02
Bitwise.band(item.flag, 0x02) != 0 ->
%{item | flag: item.flag - 0x02}
# KARMA_USE flag = 0x04
Bitwise.band(item.flag, 0x04) != 0 ->
%{item | flag: item.flag - 0x04}
true ->
item
end
%{shop_item | item: updated_item}
end
end