4 * Created on: Nov 18, 2012
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"
26 using common::Inventory;
29 using geometry::Vector;
31 using graphics::Frame;
35 EquipMenu::EquipMenu(PartyMenu *parent, int 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);
51 void EquipMenu::OnEnterState(SDL_Surface *) {
52 equipmentMenu.SetInactive();
53 inventoryMenu.SetInactive();
56 void EquipMenu::OnExitState(SDL_Surface *) {
60 void EquipMenu::OnResumeState(SDL_Surface *) {
64 void EquipMenu::OnPauseState(SDL_Surface *) {
69 void EquipMenu::OnResize(int width, int height) {
74 void EquipMenu::HandleEvents(const Input &input) {
75 if (input.JustPressed(Input::SHOULDER_LEFT)) {
78 if (input.JustPressed(Input::SHOULDER_RIGHT)) {
81 if (actionMenu.IsActive()) {
82 if (input.JustPressed(Input::PAD_UP)) {
83 actionMenu.PreviousRow();
85 if (input.JustPressed(Input::PAD_DOWN)) {
88 if (input.JustPressed(Input::ACTION_A)) {
89 switch (actionMenu.Selected()) {
92 actionMenu.SetSelected();
93 equipmentMenu.SetActive();
95 case CHOICE_STRONGEST:
96 // TODO: implement "equip strongest" when items' stat effects are done
99 actionMenu.SetSelected();
100 equipmentMenu.SetActive();
102 case CHOICE_REMOVE_ALL:
103 RemoveAllEquipment();
106 actionMenu.SetSelected();
107 equipmentMenu.SetActive();
110 } else if (input.JustPressed(Input::ACTION_B)) {
113 } else if (equipmentMenu.IsActive()) {
114 if (input.JustPressed(Input::PAD_UP)) {
115 equipmentMenu.PreviousRow();
116 if (InventoryVisible()) {
120 if (input.JustPressed(Input::PAD_DOWN)) {
121 equipmentMenu.NextRow();
122 if (InventoryVisible()) {
126 if (input.JustPressed(Input::ACTION_B)) {
127 equipmentMenu.SetInactive();
128 actionMenu.SetActive();
129 } else if (input.JustPressed(Input::ACTION_A)) {
130 switch (actionMenu.Selected()) {
132 equipmentMenu.SetSelected();
133 inventoryMenu.SetActive();
135 case CHOICE_STRONGEST:
136 case CHOICE_REMOVE_ALL:
137 // invalid state, recover
138 equipmentMenu.SetInactive();
139 actionMenu.SetActive();
150 if (input.JustPressed(Input::PAD_UP)) {
151 inventoryMenu.PreviousRow();
153 if (input.JustPressed(Input::PAD_DOWN)) {
154 inventoryMenu.NextRow();
156 if (input.JustPressed(Input::ACTION_A)) {
158 inventoryMenu.SetInactive();
159 equipmentMenu.SetActive();
160 } else if (input.JustPressed(Input::ACTION_B)) {
161 inventoryMenu.SetInactive();
162 equipmentMenu.SetActive();
167 void EquipMenu::UpdateWorld(float deltaT) {
171 void EquipMenu::Render(SDL_Surface *screen) {
172 Vector<int> offset((screen->w - Width()) / 2, (screen->h - Height()) / 2);
173 Vector<int> shoulderNavOffset(
174 5 * parent->Res().statusFont->CharWidth(),
175 parent->Res().statusFont->CharHeight());
176 Vector<int> statsOffset(
177 4 * parent->Res().statusFont->CharWidth(),
178 8 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
179 Vector<int> equipOffset(
180 17 * parent->Res().statusFont->CharWidth(),
181 4 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
183 parent->RenderBackground(screen);
184 parent->Res().shoulderNav->Draw(screen, offset + shoulderNavOffset);
185 RenderStatus(screen, offset + parent->StatusOffset(0));
186 RenderStats(screen, offset + statsOffset);
187 RenderEquipmentMenu(screen, offset + equipOffset);
188 if (InventoryVisible()) {
189 Vector<int> inventoryOffset(
190 parent->Res().statusFont->CharWidth(),
191 17 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
192 RenderInventoryMenu(screen, offset + inventoryOffset);
194 Vector<int> menuOffset(
195 15 * parent->Res().statusFont->CharWidth(),
196 17 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
197 RenderActionMenu(screen, offset + menuOffset);
201 int EquipMenu::Width() const {
202 return parent->Width();
205 int EquipMenu::Height() const {
206 return parent->Height();
209 void EquipMenu::RenderStatus(SDL_Surface *screen, const Vector<int> &offset) const {
210 parent->GetHeroStatus(cursor).Render(screen, offset);
213 void EquipMenu::RenderStats(SDL_Surface *screen, const Vector<int> &offset) const {
214 const Stats &stats(GetHero().GetStats());
215 Vector<int> lineBreak(0, parent->Res().statusFont->CharHeight());
217 Vector<int> position(offset);
218 RenderStatsLine(parent->Res().atpLabel, stats.Attack(), screen, position);
220 position += lineBreak;
221 RenderStatsLine(parent->Res().dfpLabel, stats.Defense(), screen, position);
223 position += lineBreak;
224 RenderStatsLine(parent->Res().strLabel, stats.Strength(), screen, position);
226 position += lineBreak;
227 RenderStatsLine(parent->Res().aglLabel, stats.Agility(), screen, position);
229 position += lineBreak;
230 RenderStatsLine(parent->Res().intLabel, stats.Intelligence(), screen, position);
232 position += lineBreak;
233 RenderStatsLine(parent->Res().gutLabel, stats.Gut(), screen, position);
235 position += lineBreak;
236 RenderStatsLine(parent->Res().mgrLabel, stats.MagicResistance(), screen, position);
239 void EquipMenu::RenderStatsLine(const char *label, int number, SDL_Surface *screen, const Vector<int> &position) const {
240 const Font &font(*parent->Res().statusFont);
241 const Vector<int> numberOffset(4 * font.CharWidth(), 0);
243 font.DrawString(label, screen, position, 3);
244 font.DrawNumber(number, screen, position + numberOffset, 3);
247 void EquipMenu::RenderEquipmentMenu(SDL_Surface *screen, const Vector<int> &offset) const {
248 equipmentMenu.Draw(screen, offset);
251 void EquipMenu::RenderActionMenu(SDL_Surface *screen, const Vector<int> &offset) const {
252 const Font &font(*parent->Res().statusFont);
253 const Frame &frame(*parent->Res().statusFrame);
254 const Vector<int> menuOffset(3 * font.CharWidth(), font.CharHeight() + font.CharHeight() / 2);
256 frame.Draw(screen, offset, 15 * font.CharWidth(), 10 * font.CharHeight());
257 actionMenu.Draw(screen, offset + menuOffset);
260 void EquipMenu::RenderInventoryMenu(SDL_Surface *screen, const Vector<int> &offset) const {
261 const Font &font(*parent->Res().normalFont);
262 const Frame &frame(*parent->Res().statusFrame);
263 const Vector<int> menuOffset(3 * font.CharWidth(), font.CharHeight() + font.CharHeight() / 4);
265 frame.Draw(screen, offset, 30 * font.CharWidth(), 11 * font.CharHeight());
266 inventoryMenu.Draw(screen, offset + menuOffset);
270 void EquipMenu::NextHero() {
271 cursor = (cursor + 1) % parent->Game().state->partySize;
273 if (InventoryVisible()) {
278 void EquipMenu::PreviousHero() {
279 cursor = (cursor + parent->Game().state->partySize - 1) % parent->Game().state->partySize;
281 if (InventoryVisible()) {
286 Hero &EquipMenu::GetHero() {
287 return *parent->Game().state->party[cursor];
290 const Hero &EquipMenu::GetHero() const {
291 return *parent->Game().state->party[cursor];
295 void EquipMenu::LoadEquipment() {
296 equipmentMenu.Clear();
297 for (int i = 0; i < Hero::EQUIP_COUNT; ++i) {
298 if (GetHero().Equipped(Hero::EquipSlot(i))) {
299 const Item *item(GetHero().Equipment(Hero::EquipSlot(i)));
300 equipmentMenu.Add(item->Name(), item, true, item->MenuIcon());
302 equipmentMenu.Add(parent->Res().noEquipmentText, 0);
307 void EquipMenu::RemoveAllEquipment() {
308 Inventory &inv(parent->Game().state->inventory);
309 for (int i = 0; i < Hero::EQUIP_COUNT; ++i) {
310 if (GetHero().Equipped(Hero::EquipSlot(i))
311 && inv.Add(GetHero().Equipment(Hero::EquipSlot(i)), 1)) {
312 GetHero().RemoveEquipment(Hero::EquipSlot(i));
318 void EquipMenu::RemoveItem() {
319 Inventory &inv(parent->Game().state->inventory);
320 Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
322 if (GetHero().Equipped(slot) && inv.Add(GetHero().Equipment(slot), 1)) {
323 GetHero().RemoveEquipment(slot);
329 void EquipMenu::DropItem() {
330 GetHero().RemoveEquipment(Hero::EquipSlot(equipmentMenu.SelectedIndex()));
335 bool EquipMenu::InventoryVisible() const {
336 return !actionMenu.IsActive() && actionMenu.Selected() == CHOICE_EQUIP;
339 void EquipMenu::LoadInventory() {
340 const Inventory &inv = parent->Game().state->inventory;
341 const Hero &hero = GetHero();
342 const Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
344 inventoryMenu.Clear();
345 for (int i = 0; i < inv.MaxItems(); ++i) {
346 const Item *item = inv.ItemAt(i);
347 if (item && item->EquipableAt(slot)) {
348 inventoryMenu.Add(item->Name(), item, hero.CanEquip(*item),
349 item->MenuIcon(), inv.ItemCountAt(i));
354 void EquipMenu::EquipSelected() {
355 Inventory &inv = parent->Game().state->inventory;
356 Hero &hero = GetHero();
357 const Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
359 const Item *selected = inventoryMenu.Selected();
360 const Item *equipped = equipmentMenu.Selected();
362 if (!hero.CanEquip(*selected)) {
363 // TODO: error noise and blur
367 inv.Remove(selected, 1);
368 if (!inv.Add(equipped, 1)) {
370 inv.Add(selected, 1);
371 // TODO: error noise, blur, message?
375 hero.SetEquipment(slot, selected);