3 #include "HeroStatus.h"
6 #include "../app/Application.h"
7 #include "../app/Input.h"
8 #include "../common/GameConfig.h"
9 #include "../common/GameState.h"
10 #include "../common/Hero.h"
11 #include "../common/Inventory.h"
12 #include "../common/Item.h"
13 #include "../common/Stats.h"
14 #include "../graphics/Font.h"
15 #include "../graphics/Frame.h"
16 #include "../math/Vector.h"
20 using common::Inventory;
25 using graphics::Frame;
29 EquipMenu::EquipMenu(PartyMenu *parent, int cursor)
32 , actionMenu(*parent->Res().equipmentActionMenuProperties)
33 , equipmentMenu(*parent->Res().equipmentMenuProperties)
34 , inventoryMenu(*parent->Res().inventoryMenuProperties) {
35 actionMenu.Add(parent->Res().equipMenuEquipLabel, CHOICE_EQUIP);
36 actionMenu.Add(parent->Res().equipMenuStrongestLabel, CHOICE_STRONGEST);
37 actionMenu.Add(parent->Res().equipMenuRemoveLabel, CHOICE_REMOVE);
38 actionMenu.Add(parent->Res().equipMenuRemoveAllLabel, CHOICE_REMOVE_ALL);
39 actionMenu.Add(parent->Res().equipMenuDropLabel, CHOICE_DROP);
45 void EquipMenu::OnEnterState(SDL_Surface *) {
46 equipmentMenu.SetInactive();
47 inventoryMenu.SetInactive();
50 void EquipMenu::OnExitState(SDL_Surface *) {
54 void EquipMenu::OnResumeState(SDL_Surface *) {
58 void EquipMenu::OnPauseState(SDL_Surface *) {
63 void EquipMenu::OnResize(int width, int height) {
68 void EquipMenu::HandleEvents(const Input &input) {
69 if (input.JustPressed(Input::SHOULDER_LEFT)) {
72 if (input.JustPressed(Input::SHOULDER_RIGHT)) {
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:
90 // TODO: implement "equip strongest" when items' stat effects are done
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(Uint32 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;
267 if (InventoryVisible()) {
272 void EquipMenu::PreviousHero() {
273 cursor = (cursor + parent->Game().state->partySize - 1) % parent->Game().state->partySize;
275 if (InventoryVisible()) {
280 Hero &EquipMenu::GetHero() {
281 return *parent->Game().state->party[cursor];
284 const Hero &EquipMenu::GetHero() const {
285 return *parent->Game().state->party[cursor];
289 void EquipMenu::LoadEquipment() {
290 equipmentMenu.Clear();
291 for (int i = 0; i < Hero::EQUIP_COUNT; ++i) {
292 if (GetHero().Equipped(Hero::EquipSlot(i))) {
293 const Item *item(GetHero().Equipment(Hero::EquipSlot(i)));
294 equipmentMenu.Add(item->Name(), item, true, item->MenuIcon());
296 equipmentMenu.Add(parent->Res().noEquipmentText, 0);
301 void EquipMenu::RemoveAllEquipment() {
302 Inventory &inv(parent->Game().state->inventory);
303 for (int i = 0; i < Hero::EQUIP_COUNT; ++i) {
304 if (GetHero().Equipped(Hero::EquipSlot(i))
305 && inv.Add(GetHero().Equipment(Hero::EquipSlot(i)), 1)) {
306 GetHero().RemoveEquipment(Hero::EquipSlot(i));
312 void EquipMenu::RemoveItem() {
313 Inventory &inv(parent->Game().state->inventory);
314 Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
316 if (GetHero().Equipped(slot) && inv.Add(GetHero().Equipment(slot), 1)) {
317 GetHero().RemoveEquipment(slot);
323 void EquipMenu::DropItem() {
324 GetHero().RemoveEquipment(Hero::EquipSlot(equipmentMenu.SelectedIndex()));
329 bool EquipMenu::InventoryVisible() const {
330 return !actionMenu.IsActive() && actionMenu.Selected() == CHOICE_EQUIP;
333 void EquipMenu::LoadInventory() {
334 const Inventory &inv = parent->Game().state->inventory;
335 const Hero &hero = GetHero();
336 const Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
338 inventoryMenu.Clear();
339 for (int i = 0; i < inv.MaxItems(); ++i) {
340 const Item *item = inv.ItemAt(i);
341 if (item && item->EquipableAt(slot)) {
342 inventoryMenu.Add(item->Name(), item, hero.CanEquip(*item),
343 item->MenuIcon(), inv.ItemCountAt(i));
348 void EquipMenu::EquipSelected() {
349 Inventory &inv = parent->Game().state->inventory;
350 Hero &hero = GetHero();
351 const Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
353 const Item *selected = inventoryMenu.Selected();
354 const Item *equipped = equipmentMenu.Selected();
356 if (!hero.CanEquip(*selected)) {
357 // TODO: error noise and blur
361 inv.Remove(selected, 1);
362 if (!inv.Add(equipped, 1)) {
364 inv.Add(selected, 1);
365 // TODO: error noise, blur, message?
369 hero.SetEquipment(slot, selected);