1-- All game items that could appear in this menu
2
3local font, font_size = "Comicoro", 16
4
5-- Items to never show in the inventory, even if other criteria is met
6local blacklist = {
7  'running_shoes',
8}
9
10-- Return true if the given item is blacklisted
11local function in_blacklist(item)
12  local given_item = item:get_name()
13  for _, blacklist_item in ipairs(blacklist) do
14    if given_item == blacklist_item then return true end
15  end
16  return false
17end
18
19
20-- Get the XY for an item sprite based on its position
21local function get_slot_xy(i)
22
23  local r = math.ceil(i/5) -- row of this slot
24  local x = ((i-1)%5)*24
25  local y = (r-1)*24
26
27  return x, y
28end
29
30-- Show only some game items on the inventory screen
31local function is_owned_equipment(item)
32  if item:get_savegame_variable() -- the item is saved
33     and item:get_variant() > 0 -- player owns the item
34     and item:is_assignable() -- item is equipment
35     and not item:is_key_item() -- not a key item
36  then
37    return true end
38end
39
40local function is_owned_key_item(item)
41  return item:get_savegame_variable() -- the item is saved
42         and item:get_variant() > 0 -- player owns the item
43         and item:is_key_item() -- is a key item
44end
45
46
47local inventory = {}
48
49function inventory:initialize()
50  local font, font_size = "Comicoro", 16
51
52  -- Graphics
53  self.menu = sol.surface.create(144, 48)
54  self.menu_bg = sol.sprite.create("menus/tool_select_bg")
55  self.item_sheet = sol.sprite.create("entities/items")
56  self.cursor_sprite = sol.sprite.create("menus/cursor")
57  self.equip_frame = sol.sprite.create("menus/equip_frame")
58  self.tools_text = sol.text_surface.create({text_key="menus.inventory.tools", font=font, font_size=font_size})
59  self.stuff_menu = sol.surface.create(144, 56)
60  self.stuff_bg = sol.sprite.create("menus/stuff_bg")
61
62  self.card = sol.surface.create(88, 48)
63  self.card_bg = sol.sprite.create("menus/id_card/card")
64  self.logo = sol.sprite.create("menus/id_card/logo")
65
66  self.exit_button = sol.surface.create(32, 16)
67  self.exit_button:fill_color({198, 34, 0})
68  self.exit_text = sol.text_surface.create({text_key="menus.inventory.exit", font=font, font_size=font_size})
69
70  self.save_button = sol.surface.create(32, 16)
71  self.save_button:fill_color({198, 34, 0})
72  self.save_text = sol.text_surface.create({text_key="menus.inventory.save", font=font, font_size=font_size})
73end
74
75function inventory:on_started()
76  local game = sol.main.game
77  local all_items = sol.main.get_resource_ids("item")
78
79  game:get_hero():freeze()
80
81  -- Set items that should show in the inventory
82  self.tool_items = {}
83  self.key_items = {}
84  for _, item_key in ipairs(all_items) do
85    local item = game:get_item(item_key)
86    local blacklisted = in_blacklist(item)
87    if is_owned_equipment(item) and not blacklisted then
88      table.insert(self.tool_items, item_key)
89    end
90    if is_owned_key_item(item) and not blacklisted then
91      table.insert(self.key_items, item_key)
92    end
93  end
94
95  -- Set initial cursor position
96  self.cursor = 0
97  local slot_1 = game:get_item_assigned(1)
98  if slot_1 then
99    for i, item in ipairs(self.tool_items) do
100      if item == slot_1:get_name() then
101        self.cursor = i break
102      end
103    end
104  end
105end
106
107function inventory:on_draw(dst_surface)
108  local game = sol.main.game
109
110  self.menu:draw(dst_surface, 8, 8)
111  self.menu_bg:draw(self.menu)
112  self.tools_text:draw(self.menu, 8, 7)
113
114  self.stuff_menu:draw(dst_surface, 8, 60)
115  self.stuff_bg:draw(self.stuff_menu)
116
117  -- Draw tool items, loop through inventory
118  for i, item in ipairs(self.tool_items) do
119    if i > 5 then break end -- 5 columns, 1 row
120    if game:has_item(item) then
121      self.item_sheet:set_animation(item) -- all items are in one sheet
122      local x, y = get_slot_xy(i) -- item slot XY
123      local ox, oy = self.item_sheet:get_origin() -- origin offset
124      x = x + 8
125      y = y + 19
126      self.item_sheet:draw(self.menu, x+ox, y+oy) -- draw item
127      if game:get_item_assigned(1) == game:get_item(item) then
128        self.equip_frame:draw(self.menu, x, y) -- draw "EQUIP" frame
129      end
130      if self.cursor == i then
131        self.cursor_sprite:draw(self.menu, x, y) -- draw cursor
132      end
133    end
134  end
135
136  -- Draw key items
137  for i, item in ipairs(self.key_items) do
138    if i > 10 then break end -- 5 columns, 2 rows
139    if game:has_item(item) then
140      self.item_sheet:set_animation(item) -- all items are in one sheet
141      local x, y = get_slot_xy(i) -- item slot XY
142      local ox, oy = self.item_sheet:get_origin() -- origin offset
143      self.item_sheet:draw(self.stuff_menu, x+ox+8, y+oy+10) -- draw item
144    end
145  end
146
147  -- ID card
148  local card_item = game:get_item("id_card")
149  if card_item:get_variant() > 0 then
150    self.card:draw(dst_surface, 160, 8)
151    self.card_bg:draw(self.card)
152  end
153  local variants = {"usa", "evolv", "transcend"}
154  local animation = variants[card_item:get_variant()]
155  if animation then self.logo:set_animation(animation) end
156  if card_item:get_variant() < 4 then
157    self.logo:draw(self.card, 32, 24)
158  end
159
160  -- Exit button
161  self.exit_text:draw(self.exit_button, 7, 7)
162  self.exit_button:draw(dst_surface, 160, 64)
163  if self.cursor == #self.tool_items+1 then
164    self.cursor_sprite:draw(dst_surface, 168, 64) -- cancel button cursor
165  end
166
167  -- Save button
168  self.save_text:draw(self.save_button, 5, 7)
169  self.save_button:draw(dst_surface, 200, 64)
170  if self.cursor == #self.tool_items+2 then
171    self.cursor_sprite:draw(dst_surface, 208, 64)
172  end
173
174end
175
176function inventory:on_finished()
177  local game = sol.main.game
178  game:get_hero():unfreeze()
179end
180
181function inventory:on_command_pressed(command)
182  local game = sol.main.game
183  local exit_btn_pos = #self.tool_items+2
184
185  -- D-Pad controls
186  if command == "up" then
187    self.cursor = self.cursor - 5 -- up and down navigate between rows
188  elseif command == "down" then
189    self.cursor = self.cursor + 5
190  elseif command == "left" then
191    self.cursor = self.cursor - 1
192  elseif command == "right" then
193    self.cursor = self.cursor + 1
194  end
195
196  -- Cursor must be between 1 and exit_btn_pos
197  self.cursor = math.max(1, self.cursor)
198  self.cursor = math.min(self.cursor, exit_btn_pos)
199  log("Inventory cursor: " .. self.cursor)
200
201  -- Handle selection
202  if command == "action" then
203    if self.cursor == exit_btn_pos-1 then
204      return game:set_paused(false)
205    elseif self.cursor == exit_btn_pos then
206      return game:save()
207    end
208    -- Set item
209    local item = game:get_item(self.tool_items[self.cursor])
210    if item then
211      game:set_item_assigned(1, item)
212      log("Item assigned: " .. item:get_name())
213    end
214  end
215end
216
217-- Initialize when the game starts
218local game_meta = sol.main.get_metatable("game")
219game_meta:register_event("on_started", function(self)
220  inventory:initialize()
221end)
222
223return inventory
224