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 (actionMenu.IsActive()) {
76 if (input.JustPressed(Input::PAD_UP)) {
77 actionMenu.PreviousRow();
79 if (input.JustPressed(Input::PAD_DOWN)) {
82 if (input.JustPressed(Input::ACTION_A)) {
83 switch (actionMenu.Selected()) {
86 actionMenu.SetSelected();
87 equipmentMenu.SetActive();
89 case CHOICE_STRONGEST:
93 actionMenu.SetSelected();
94 equipmentMenu.SetActive();
96 case CHOICE_REMOVE_ALL:
100 actionMenu.SetSelected();
101 equipmentMenu.SetActive();
104 } else if (input.JustPressed(Input::ACTION_B)) {
107 } else if (equipmentMenu.IsActive()) {
108 if (input.JustPressed(Input::PAD_UP)) {
109 equipmentMenu.PreviousRow();
110 if (InventoryVisible()) {
114 if (input.JustPressed(Input::PAD_DOWN)) {
115 equipmentMenu.NextRow();
116 if (InventoryVisible()) {
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()) {
126 equipmentMenu.SetSelected();
127 inventoryMenu.SetActive();
129 case CHOICE_STRONGEST:
130 case CHOICE_REMOVE_ALL:
131 // invalid state, recover
132 equipmentMenu.SetInactive();
133 actionMenu.SetActive();
144 if (input.JustPressed(Input::PAD_UP)) {
145 inventoryMenu.PreviousRow();
147 if (input.JustPressed(Input::PAD_DOWN)) {
148 inventoryMenu.NextRow();
150 if (input.JustPressed(Input::ACTION_A)) {
152 inventoryMenu.SetInactive();
153 equipmentMenu.SetActive();
154 } else if (input.JustPressed(Input::ACTION_B)) {
155 inventoryMenu.SetInactive();
156 equipmentMenu.SetActive();
161 void EquipMenu::UpdateWorld(float deltaT) {
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);
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);
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);
195 int EquipMenu::Width() const {
196 return parent->Width();
199 int EquipMenu::Height() const {
200 return parent->Height();
203 void EquipMenu::RenderStatus(SDL_Surface *screen, const Vector<int> &offset) const {
204 parent->GetHeroStatus(cursor).Render(screen, offset);
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());
211 Vector<int> position(offset);
212 RenderStatsLine(parent->Res().atpLabel, stats.Attack(), screen, position);
214 position += lineBreak;
215 RenderStatsLine(parent->Res().dfpLabel, stats.Defense(), screen, position);
217 position += lineBreak;
218 RenderStatsLine(parent->Res().strLabel, stats.Strength(), screen, position);
220 position += lineBreak;
221 RenderStatsLine(parent->Res().aglLabel, stats.Agility(), screen, position);
223 position += lineBreak;
224 RenderStatsLine(parent->Res().intLabel, stats.Intelligence(), screen, position);
226 position += lineBreak;
227 RenderStatsLine(parent->Res().gutLabel, stats.Gut(), screen, position);
229 position += lineBreak;
230 RenderStatsLine(parent->Res().mgrLabel, stats.MagicResistance(), screen, position);
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);
237 font.DrawString(label, screen, position, 3);
238 font.DrawNumber(number, screen, position + numberOffset, 3);
241 void EquipMenu::RenderEquipmentMenu(SDL_Surface *screen, const Vector<int> &offset) const {
242 equipmentMenu.Draw(screen, offset);
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);
250 frame.Draw(screen, offset, 15 * font.CharWidth(), 10 * font.CharHeight());
251 actionMenu.Draw(screen, offset + menuOffset);
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);
259 frame.Draw(screen, offset, 30 * font.CharWidth(), 11 * font.CharHeight());
260 inventoryMenu.Draw(screen, offset + menuOffset);
264 void EquipMenu::NextHero() {
265 cursor = (cursor + 1) % parent->Game().state->partySize;
269 void EquipMenu::PreviousHero() {
270 cursor = (cursor + parent->Game().state->partySize - 1) % parent->Game().state->partySize;
274 Hero &EquipMenu::GetHero() {
275 return *parent->Game().state->party[cursor];
278 const Hero &EquipMenu::GetHero() const {
279 return *parent->Game().state->party[cursor];
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());
290 equipmentMenu.Add(parent->Res().noEquipmentText, 0, false);
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));
306 void EquipMenu::RemoveItem() {
307 Inventory &inv(parent->Game().state->inventory);
308 Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
310 if (GetHero().Equipped(slot) && inv.Add(GetHero().Equipment(slot), 1)) {
311 GetHero().RemoveEquipment(slot);
317 void EquipMenu::DropItem() {
318 GetHero().RemoveEquipment(Hero::EquipSlot(equipmentMenu.SelectedIndex()));
323 bool EquipMenu::InventoryVisible() const {
324 return !actionMenu.IsActive() && actionMenu.Selected() == CHOICE_EQUIP;
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());
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));
342 void EquipMenu::EquipSelected() {
343 Inventory &inv = parent->Game().state->inventory;
344 Hero &hero = GetHero();
345 const Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
347 const Item *selected = inventoryMenu.Selected();
348 const Item *equipped = equipmentMenu.Selected();
350 if (!hero.CanEquip(*selected)) {
351 // TODO: error noise and blur
355 inv.Remove(selected, 1);
356 if (!inv.Add(equipped, 1)) {
358 inv.Add(selected, 1);
359 // TODO: error noise, blur, message?
363 hero.SetEquipment(slot, selected);