]> git.localhorst.tv Git - l2e.git/blob - src/menu/EquipMenu.cpp
c60ea30a92795cb56fc85861b5ca95f03bd7f8ab
[l2e.git] / src / menu / EquipMenu.cpp
1 /*
2  * EquipMenu.cpp
3  *
4  *  Created on: Nov 18, 2012
5  *      Author: holy
6  */
7
8 #include "EquipMenu.h"
9
10 #include "HeroStatus.h"
11 #include "PartyMenu.h"
12 #include "Resources.h"
13 #include "../app/Application.h"
14 #include "../app/Input.h"
15 #include "../common/GameConfig.h"
16 #include "../common/GameState.h"
17 #include "../common/Hero.h"
18 #include "../common/Inventory.h"
19 #include "../common/Item.h"
20 #include "../common/Stats.h"
21 #include "../graphics/Font.h"
22 #include "../graphics/Frame.h"
23
24 using app::Input;
25 using common::Hero;
26 using common::Inventory;
27 using common::Item;
28 using common::Stats;
29 using geometry::Vector;
30 using graphics::Font;
31 using graphics::Frame;
32
33 namespace menu {
34
35 EquipMenu::EquipMenu(PartyMenu *parent, int cursor)
36 : parent(parent)
37 , cursor(cursor)
38 , actionMenu(*parent->Res().equipmentActionMenuProperties)
39 , equipmentMenu(*parent->Res().equipmentMenuProperties)
40 , inventoryMenu(*parent->Res().inventoryMenuProperties) {
41         actionMenu.Add(parent->Res().equipMenuEquipLabel, CHOICE_EQUIP);
42         actionMenu.Add(parent->Res().equipMenuStrongestLabel, CHOICE_STRONGEST);
43         actionMenu.Add(parent->Res().equipMenuRemoveLabel, CHOICE_REMOVE);
44         actionMenu.Add(parent->Res().equipMenuRemoveAllLabel, CHOICE_REMOVE_ALL);
45         actionMenu.Add(parent->Res().equipMenuDropLabel, CHOICE_DROP);
46
47         LoadEquipment();
48 }
49
50
51 void EquipMenu::OnEnterState(SDL_Surface *) {
52         equipmentMenu.SetInactive();
53         inventoryMenu.SetInactive();
54 }
55
56 void EquipMenu::OnExitState(SDL_Surface *) {
57
58 }
59
60 void EquipMenu::OnResumeState(SDL_Surface *) {
61
62 }
63
64 void EquipMenu::OnPauseState(SDL_Surface *) {
65
66 }
67
68
69 void EquipMenu::OnResize(int width, int height) {
70
71 }
72
73
74 void EquipMenu::HandleEvents(const Input &input) {
75         if (actionMenu.IsActive()) {
76                 if (input.JustPressed(Input::PAD_UP)) {
77                         actionMenu.PreviousRow();
78                 }
79                 if (input.JustPressed(Input::PAD_DOWN)) {
80                         actionMenu.NextRow();
81                 }
82                 if (input.JustPressed(Input::ACTION_A)) {
83                         switch (actionMenu.Selected()) {
84                                 case CHOICE_EQUIP:
85                                         LoadEquipment();
86                                         actionMenu.SetSelected();
87                                         equipmentMenu.SetActive();
88                                         break;
89                                 case CHOICE_STRONGEST:
90                                         // TODO
91                                         break;
92                                 case CHOICE_REMOVE:
93                                         actionMenu.SetSelected();
94                                         equipmentMenu.SetActive();
95                                         break;
96                                 case CHOICE_REMOVE_ALL:
97                                         RemoveAllEquipment();
98                                         break;
99                                 case CHOICE_DROP:
100                                         actionMenu.SetSelected();
101                                         equipmentMenu.SetActive();
102                                         break;
103                         }
104                 } else if (input.JustPressed(Input::ACTION_B)) {
105                         Ctrl().PopState();
106                 }
107         } else if (equipmentMenu.IsActive()) {
108                 if (input.JustPressed(Input::PAD_UP)) {
109                         equipmentMenu.PreviousRow();
110                         if (InventoryVisible()) {
111                                 LoadInventory();
112                         }
113                 }
114                 if (input.JustPressed(Input::PAD_DOWN)) {
115                         equipmentMenu.NextRow();
116                         if (InventoryVisible()) {
117                                 LoadInventory();
118                         }
119                 }
120                 if (input.JustPressed(Input::ACTION_B)) {
121                         equipmentMenu.SetInactive();
122                         actionMenu.SetActive();
123                 } else if (input.JustPressed(Input::ACTION_A)) {
124                         switch (actionMenu.Selected()) {
125                                 case CHOICE_EQUIP:
126                                         equipmentMenu.SetSelected();
127                                         inventoryMenu.SetActive();
128                                         break;
129                                 case CHOICE_STRONGEST:
130                                 case CHOICE_REMOVE_ALL:
131                                         // invalid state, recover
132                                         equipmentMenu.SetInactive();
133                                         actionMenu.SetActive();
134                                         break;
135                                 case CHOICE_REMOVE:
136                                         RemoveItem();
137                                         break;
138                                 case CHOICE_DROP:
139                                         DropItem();
140                                         break;
141                         }
142                 }
143         } else {
144                 if (input.JustPressed(Input::PAD_UP)) {
145                         inventoryMenu.PreviousRow();
146                 }
147                 if (input.JustPressed(Input::PAD_DOWN)) {
148                         inventoryMenu.NextRow();
149                 }
150                 if (input.JustPressed(Input::ACTION_A)) {
151                         // TODO: equip selected item
152                 } else if (input.JustPressed(Input::ACTION_B)) {
153                         inventoryMenu.SetInactive();
154                         equipmentMenu.SetActive();
155                 }
156         }
157 }
158
159 void EquipMenu::UpdateWorld(float deltaT) {
160
161 }
162
163 void EquipMenu::Render(SDL_Surface *screen) {
164         Vector<int> offset((screen->w - Width()) / 2, (screen->h - Height()) / 2);
165         Vector<int> shoulderNavOffset(
166                         5 * parent->Res().statusFont->CharWidth(),
167                         parent->Res().statusFont->CharHeight());
168         Vector<int> statsOffset(
169                         4 * parent->Res().statusFont->CharWidth(),
170                         8 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
171         Vector<int> equipOffset(
172                         17 * parent->Res().statusFont->CharWidth(),
173                         4 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
174
175         parent->RenderBackground(screen);
176         parent->Res().shoulderNav->Draw(screen, offset + shoulderNavOffset);
177         RenderStatus(screen, offset + parent->StatusOffset(0));
178         RenderStats(screen, offset + statsOffset);
179         RenderEquipmentMenu(screen, offset + equipOffset);
180         if (InventoryVisible()) {
181                 Vector<int> inventoryOffset(
182                                 parent->Res().statusFont->CharWidth(),
183                                 17 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
184                 RenderInventoryMenu(screen, offset + inventoryOffset);
185         } else {
186                 Vector<int> menuOffset(
187                                 15 * parent->Res().statusFont->CharWidth(),
188                                 17 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
189                 RenderActionMenu(screen, offset + menuOffset);
190         }
191 }
192
193 int EquipMenu::Width() const {
194         return parent->Width();
195 }
196
197 int EquipMenu::Height() const {
198         return parent->Height();
199 }
200
201 void EquipMenu::RenderStatus(SDL_Surface *screen, const Vector<int> &offset) const {
202         parent->GetHeroStatus(cursor).Render(screen, offset);
203 }
204
205 void EquipMenu::RenderStats(SDL_Surface *screen, const Vector<int> &offset) const {
206         const Stats &stats(GetHero().GetStats());
207         Vector<int> lineBreak(0, parent->Res().statusFont->CharHeight());
208
209         Vector<int> position(offset);
210         RenderStatsLine(parent->Res().atpLabel, stats.Attack(), screen, position);
211
212         position += lineBreak;
213         RenderStatsLine(parent->Res().dfpLabel, stats.Defense(), screen, position);
214
215         position += lineBreak;
216         RenderStatsLine(parent->Res().strLabel, stats.Strength(), screen, position);
217
218         position += lineBreak;
219         RenderStatsLine(parent->Res().aglLabel, stats.Agility(), screen, position);
220
221         position += lineBreak;
222         RenderStatsLine(parent->Res().intLabel, stats.Intelligence(), screen, position);
223
224         position += lineBreak;
225         RenderStatsLine(parent->Res().gutLabel, stats.Gut(), screen, position);
226
227         position += lineBreak;
228         RenderStatsLine(parent->Res().mgrLabel, stats.MagicResistance(), screen, position);
229 }
230
231 void EquipMenu::RenderStatsLine(const char *label, int number, SDL_Surface *screen, const Vector<int> &position) const {
232         const Font &font(*parent->Res().statusFont);
233         const Vector<int> numberOffset(4 * font.CharWidth(), 0);
234
235         font.DrawString(label, screen, position, 3);
236         font.DrawNumber(number, screen, position + numberOffset, 3);
237 }
238
239 void EquipMenu::RenderEquipmentMenu(SDL_Surface *screen, const Vector<int> &offset) const {
240         equipmentMenu.Draw(screen, offset);
241 }
242
243 void EquipMenu::RenderActionMenu(SDL_Surface *screen, const Vector<int> &offset) const {
244         const Font &font(*parent->Res().statusFont);
245         const Frame &frame(*parent->Res().statusFrame);
246         const Vector<int> menuOffset(3 * font.CharWidth(), font.CharHeight() + font.CharHeight() / 2);
247
248         frame.Draw(screen, offset, 15 * font.CharWidth(), 10 * font.CharHeight());
249         actionMenu.Draw(screen, offset + menuOffset);
250 }
251
252 void EquipMenu::RenderInventoryMenu(SDL_Surface *screen, const Vector<int> &offset) const {
253         const Font &font(*parent->Res().normalFont);
254         const Frame &frame(*parent->Res().statusFrame);
255         const Vector<int> menuOffset(3 * font.CharWidth(), font.CharHeight() + font.CharHeight() / 4);
256
257         frame.Draw(screen, offset, 30 * font.CharWidth(), 11 * font.CharHeight());
258         inventoryMenu.Draw(screen, offset + menuOffset);
259 }
260
261
262 void EquipMenu::NextHero() {
263         cursor = (cursor + 1) % parent->Game().state->partySize;
264         LoadEquipment();
265 }
266
267 void EquipMenu::PreviousHero() {
268         cursor = (cursor + parent->Game().state->partySize - 1) % parent->Game().state->partySize;
269         LoadEquipment();
270 }
271
272 Hero &EquipMenu::GetHero() {
273         return *parent->Game().state->party[cursor];
274 }
275
276 const Hero &EquipMenu::GetHero() const {
277         return *parent->Game().state->party[cursor];
278 }
279
280
281 void EquipMenu::LoadEquipment() {
282         equipmentMenu.Clear();
283         for (int i = 0; i < Hero::EQUIP_COUNT; ++i) {
284                 if (GetHero().Equipped(Hero::EquipSlot(i))) {
285                         const Item *item(GetHero().Equipment(Hero::EquipSlot(i)));
286                         equipmentMenu.Add(item->Name(), item, true, item->MenuIcon());
287                 } else {
288                         equipmentMenu.Add(parent->Res().noEquipmentText, 0, false);
289                 }
290         }
291 }
292
293 void EquipMenu::RemoveAllEquipment() {
294         Inventory &inv(parent->Game().state->inventory);
295         for (int i = 0; i < Hero::EQUIP_COUNT; ++i) {
296                 if (GetHero().Equipped(Hero::EquipSlot(i))
297                                 && inv.Add(GetHero().Equipment(Hero::EquipSlot(i)), 1)) {
298                         GetHero().RemoveEquipment(Hero::EquipSlot(i));
299                 }
300         }
301         LoadEquipment();
302 }
303
304 void EquipMenu::RemoveItem() {
305         Inventory &inv(parent->Game().state->inventory);
306         Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
307
308         if (GetHero().Equipped(slot) && inv.Add(GetHero().Equipment(slot), 1)) {
309                 GetHero().RemoveEquipment(slot);
310         }
311
312         LoadEquipment();
313 }
314
315 void EquipMenu::DropItem() {
316         GetHero().RemoveEquipment(Hero::EquipSlot(equipmentMenu.SelectedIndex()));
317         LoadEquipment();
318 }
319
320
321 bool EquipMenu::InventoryVisible() const {
322         return !actionMenu.IsActive() && actionMenu.Selected() == CHOICE_EQUIP;
323 }
324
325 void EquipMenu::LoadInventory() {
326         const Inventory &inv = parent->Game().state->inventory;
327         const Hero &hero = GetHero();
328         const Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
329
330         inventoryMenu.Clear();
331         for (int i = 0; i < inv.MaxItems(); ++i) {
332                 const Item *item = inv.ItemAt(i);
333                 if (item && item->EquipableAt(slot)) {
334                         inventoryMenu.Add(item->Name(), item, hero.CanEquip(*item),
335                                         item->MenuIcon(), inv.ItemCountAt(i));
336                 }
337         }
338 }
339
340 }