]> git.localhorst.tv Git - l2e.git/blob - src/menu/EquipMenu.cpp
0caff55467b5779a00f72b559d647c6e80cf16d5
[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                         EquipSelected();
152                         inventoryMenu.SetInactive();
153                         equipmentMenu.SetActive();
154                 } else if (input.JustPressed(Input::ACTION_B)) {
155                         inventoryMenu.SetInactive();
156                         equipmentMenu.SetActive();
157                 }
158         }
159 }
160
161 void EquipMenu::UpdateWorld(float deltaT) {
162
163 }
164
165 void EquipMenu::Render(SDL_Surface *screen) {
166         Vector<int> offset((screen->w - Width()) / 2, (screen->h - Height()) / 2);
167         Vector<int> shoulderNavOffset(
168                         5 * parent->Res().statusFont->CharWidth(),
169                         parent->Res().statusFont->CharHeight());
170         Vector<int> statsOffset(
171                         4 * parent->Res().statusFont->CharWidth(),
172                         8 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
173         Vector<int> equipOffset(
174                         17 * parent->Res().statusFont->CharWidth(),
175                         4 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
176
177         parent->RenderBackground(screen);
178         parent->Res().shoulderNav->Draw(screen, offset + shoulderNavOffset);
179         RenderStatus(screen, offset + parent->StatusOffset(0));
180         RenderStats(screen, offset + statsOffset);
181         RenderEquipmentMenu(screen, offset + equipOffset);
182         if (InventoryVisible()) {
183                 Vector<int> inventoryOffset(
184                                 parent->Res().statusFont->CharWidth(),
185                                 17 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
186                 RenderInventoryMenu(screen, offset + inventoryOffset);
187         } else {
188                 Vector<int> menuOffset(
189                                 15 * parent->Res().statusFont->CharWidth(),
190                                 17 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
191                 RenderActionMenu(screen, offset + menuOffset);
192         }
193 }
194
195 int EquipMenu::Width() const {
196         return parent->Width();
197 }
198
199 int EquipMenu::Height() const {
200         return parent->Height();
201 }
202
203 void EquipMenu::RenderStatus(SDL_Surface *screen, const Vector<int> &offset) const {
204         parent->GetHeroStatus(cursor).Render(screen, offset);
205 }
206
207 void EquipMenu::RenderStats(SDL_Surface *screen, const Vector<int> &offset) const {
208         const Stats &stats(GetHero().GetStats());
209         Vector<int> lineBreak(0, parent->Res().statusFont->CharHeight());
210
211         Vector<int> position(offset);
212         RenderStatsLine(parent->Res().atpLabel, stats.Attack(), screen, position);
213
214         position += lineBreak;
215         RenderStatsLine(parent->Res().dfpLabel, stats.Defense(), screen, position);
216
217         position += lineBreak;
218         RenderStatsLine(parent->Res().strLabel, stats.Strength(), screen, position);
219
220         position += lineBreak;
221         RenderStatsLine(parent->Res().aglLabel, stats.Agility(), screen, position);
222
223         position += lineBreak;
224         RenderStatsLine(parent->Res().intLabel, stats.Intelligence(), screen, position);
225
226         position += lineBreak;
227         RenderStatsLine(parent->Res().gutLabel, stats.Gut(), screen, position);
228
229         position += lineBreak;
230         RenderStatsLine(parent->Res().mgrLabel, stats.MagicResistance(), screen, position);
231 }
232
233 void EquipMenu::RenderStatsLine(const char *label, int number, SDL_Surface *screen, const Vector<int> &position) const {
234         const Font &font(*parent->Res().statusFont);
235         const Vector<int> numberOffset(4 * font.CharWidth(), 0);
236
237         font.DrawString(label, screen, position, 3);
238         font.DrawNumber(number, screen, position + numberOffset, 3);
239 }
240
241 void EquipMenu::RenderEquipmentMenu(SDL_Surface *screen, const Vector<int> &offset) const {
242         equipmentMenu.Draw(screen, offset);
243 }
244
245 void EquipMenu::RenderActionMenu(SDL_Surface *screen, const Vector<int> &offset) const {
246         const Font &font(*parent->Res().statusFont);
247         const Frame &frame(*parent->Res().statusFrame);
248         const Vector<int> menuOffset(3 * font.CharWidth(), font.CharHeight() + font.CharHeight() / 2);
249
250         frame.Draw(screen, offset, 15 * font.CharWidth(), 10 * font.CharHeight());
251         actionMenu.Draw(screen, offset + menuOffset);
252 }
253
254 void EquipMenu::RenderInventoryMenu(SDL_Surface *screen, const Vector<int> &offset) const {
255         const Font &font(*parent->Res().normalFont);
256         const Frame &frame(*parent->Res().statusFrame);
257         const Vector<int> menuOffset(3 * font.CharWidth(), font.CharHeight() + font.CharHeight() / 4);
258
259         frame.Draw(screen, offset, 30 * font.CharWidth(), 11 * font.CharHeight());
260         inventoryMenu.Draw(screen, offset + menuOffset);
261 }
262
263
264 void EquipMenu::NextHero() {
265         cursor = (cursor + 1) % parent->Game().state->partySize;
266         LoadEquipment();
267 }
268
269 void EquipMenu::PreviousHero() {
270         cursor = (cursor + parent->Game().state->partySize - 1) % parent->Game().state->partySize;
271         LoadEquipment();
272 }
273
274 Hero &EquipMenu::GetHero() {
275         return *parent->Game().state->party[cursor];
276 }
277
278 const Hero &EquipMenu::GetHero() const {
279         return *parent->Game().state->party[cursor];
280 }
281
282
283 void EquipMenu::LoadEquipment() {
284         equipmentMenu.Clear();
285         for (int i = 0; i < Hero::EQUIP_COUNT; ++i) {
286                 if (GetHero().Equipped(Hero::EquipSlot(i))) {
287                         const Item *item(GetHero().Equipment(Hero::EquipSlot(i)));
288                         equipmentMenu.Add(item->Name(), item, true, item->MenuIcon());
289                 } else {
290                         equipmentMenu.Add(parent->Res().noEquipmentText, 0);
291                 }
292         }
293 }
294
295 void EquipMenu::RemoveAllEquipment() {
296         Inventory &inv(parent->Game().state->inventory);
297         for (int i = 0; i < Hero::EQUIP_COUNT; ++i) {
298                 if (GetHero().Equipped(Hero::EquipSlot(i))
299                                 && inv.Add(GetHero().Equipment(Hero::EquipSlot(i)), 1)) {
300                         GetHero().RemoveEquipment(Hero::EquipSlot(i));
301                 }
302         }
303         LoadEquipment();
304 }
305
306 void EquipMenu::RemoveItem() {
307         Inventory &inv(parent->Game().state->inventory);
308         Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
309
310         if (GetHero().Equipped(slot) && inv.Add(GetHero().Equipment(slot), 1)) {
311                 GetHero().RemoveEquipment(slot);
312         }
313
314         LoadEquipment();
315 }
316
317 void EquipMenu::DropItem() {
318         GetHero().RemoveEquipment(Hero::EquipSlot(equipmentMenu.SelectedIndex()));
319         LoadEquipment();
320 }
321
322
323 bool EquipMenu::InventoryVisible() const {
324         return !actionMenu.IsActive() && actionMenu.Selected() == CHOICE_EQUIP;
325 }
326
327 void EquipMenu::LoadInventory() {
328         const Inventory &inv = parent->Game().state->inventory;
329         const Hero &hero = GetHero();
330         const Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
331
332         inventoryMenu.Clear();
333         for (int i = 0; i < inv.MaxItems(); ++i) {
334                 const Item *item = inv.ItemAt(i);
335                 if (item && item->EquipableAt(slot)) {
336                         inventoryMenu.Add(item->Name(), item, hero.CanEquip(*item),
337                                         item->MenuIcon(), inv.ItemCountAt(i));
338                 }
339         }
340 }
341
342 void EquipMenu::EquipSelected() {
343         Inventory &inv = parent->Game().state->inventory;
344         Hero &hero = GetHero();
345         const Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
346
347         const Item *selected = inventoryMenu.Selected();
348         const Item *equipped = equipmentMenu.Selected();
349
350         if (!hero.CanEquip(*selected)) {
351                 // TODO: error noise and blur
352                 return;
353         }
354
355         inv.Remove(selected, 1);
356         if (!inv.Add(equipped, 1)) {
357                 // roll back
358                 inv.Add(selected, 1);
359                 // TODO: error noise, blur, message?
360                 return;
361         }
362
363         hero.SetEquipment(slot, selected);
364         LoadEquipment();
365         LoadInventory();
366 }
367
368 }