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 actionMenu.StartAnimation(Ctrl());
47 equipmentMenu.SetInactive();
48 equipmentMenu.StartAnimation(Ctrl());
49 inventoryMenu.SetInactive();
50 inventoryMenu.StartAnimation(Ctrl());
53 void EquipMenu::OnExitState(SDL_Surface *) {
57 void EquipMenu::OnResumeState(SDL_Surface *) {
61 void EquipMenu::OnPauseState(SDL_Surface *) {
66 void EquipMenu::OnResize(int width, int height) {
71 void EquipMenu::HandleEvents(const Input &input) {
72 if (input.JustPressed(Input::SHOULDER_LEFT)) {
75 if (input.JustPressed(Input::SHOULDER_RIGHT)) {
78 if (actionMenu.IsActive()) {
79 if (input.JustPressed(Input::PAD_UP)) {
80 actionMenu.PreviousRow();
82 if (input.JustPressed(Input::PAD_DOWN)) {
85 if (input.JustPressed(Input::ACTION_A)) {
86 switch (actionMenu.Selected()) {
89 actionMenu.SetSelected();
90 equipmentMenu.SetActive();
92 case CHOICE_STRONGEST:
93 // TODO: implement "equip strongest" when items' stat effects are done
96 actionMenu.SetSelected();
97 equipmentMenu.SetActive();
99 case CHOICE_REMOVE_ALL:
100 RemoveAllEquipment();
103 actionMenu.SetSelected();
104 equipmentMenu.SetActive();
107 } else if (input.JustPressed(Input::ACTION_B)) {
110 } else if (equipmentMenu.IsActive()) {
111 if (input.JustPressed(Input::PAD_UP)) {
112 equipmentMenu.PreviousRow();
113 if (InventoryVisible()) {
117 if (input.JustPressed(Input::PAD_DOWN)) {
118 equipmentMenu.NextRow();
119 if (InventoryVisible()) {
123 if (input.JustPressed(Input::ACTION_B)) {
124 equipmentMenu.SetInactive();
125 actionMenu.SetActive();
126 } else if (input.JustPressed(Input::ACTION_A)) {
127 switch (actionMenu.Selected()) {
129 equipmentMenu.SetSelected();
130 inventoryMenu.SetActive();
132 case CHOICE_STRONGEST:
133 case CHOICE_REMOVE_ALL:
134 // invalid state, recover
135 equipmentMenu.SetInactive();
136 actionMenu.SetActive();
147 if (input.JustPressed(Input::PAD_UP)) {
148 inventoryMenu.PreviousRow();
150 if (input.JustPressed(Input::PAD_DOWN)) {
151 inventoryMenu.NextRow();
153 if (input.JustPressed(Input::ACTION_A)) {
155 inventoryMenu.SetInactive();
156 equipmentMenu.SetActive();
157 } else if (input.JustPressed(Input::ACTION_B)) {
158 inventoryMenu.SetInactive();
159 equipmentMenu.SetActive();
164 void EquipMenu::UpdateWorld(Uint32 deltaT) {
168 void EquipMenu::Render(SDL_Surface *screen) {
169 Vector<int> offset((screen->w - Width()) / 2, (screen->h - Height()) / 2);
170 Vector<int> shoulderNavOffset(
171 5 * parent->Res().statusFont->CharWidth(),
172 parent->Res().statusFont->CharHeight());
173 Vector<int> statsOffset(
174 4 * parent->Res().statusFont->CharWidth(),
175 8 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
176 Vector<int> equipOffset(
177 17 * parent->Res().statusFont->CharWidth(),
178 4 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
180 parent->RenderBackground(screen);
181 parent->Res().shoulderNav->Draw(screen, offset + shoulderNavOffset);
182 RenderStatus(screen, offset + parent->StatusOffset(0));
183 RenderStats(screen, offset + statsOffset);
184 RenderEquipmentMenu(screen, offset + equipOffset);
185 if (InventoryVisible()) {
186 Vector<int> inventoryOffset(
187 parent->Res().statusFont->CharWidth(),
188 17 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
189 RenderInventoryMenu(screen, offset + inventoryOffset);
191 Vector<int> menuOffset(
192 15 * parent->Res().statusFont->CharWidth(),
193 17 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
194 RenderActionMenu(screen, offset + menuOffset);
198 int EquipMenu::Width() const {
199 return parent->Width();
202 int EquipMenu::Height() const {
203 return parent->Height();
206 void EquipMenu::RenderStatus(SDL_Surface *screen, const Vector<int> &offset) const {
207 parent->GetHeroStatus(cursor).Render(screen, offset);
210 void EquipMenu::RenderStats(SDL_Surface *screen, const Vector<int> &offset) const {
211 const Stats &stats(GetHero().GetStats());
212 Vector<int> lineBreak(0, parent->Res().statusFont->CharHeight());
214 Vector<int> position(offset);
215 RenderStatsLine(parent->Res().atpLabel, stats.Attack(), screen, position);
217 position += lineBreak;
218 RenderStatsLine(parent->Res().dfpLabel, stats.Defense(), screen, position);
220 position += lineBreak;
221 RenderStatsLine(parent->Res().strLabel, stats.Strength(), screen, position);
223 position += lineBreak;
224 RenderStatsLine(parent->Res().aglLabel, stats.Agility(), screen, position);
226 position += lineBreak;
227 RenderStatsLine(parent->Res().intLabel, stats.Intelligence(), screen, position);
229 position += lineBreak;
230 RenderStatsLine(parent->Res().gutLabel, stats.Gut(), screen, position);
232 position += lineBreak;
233 RenderStatsLine(parent->Res().mgrLabel, stats.MagicResistance(), screen, position);
236 void EquipMenu::RenderStatsLine(const char *label, int number, SDL_Surface *screen, const Vector<int> &position) const {
237 const Font &font(*parent->Res().statusFont);
238 const Vector<int> numberOffset(4 * font.CharWidth(), 0);
240 font.DrawString(label, screen, position, 3);
241 font.DrawNumber(number, screen, position + numberOffset, 3);
244 void EquipMenu::RenderEquipmentMenu(SDL_Surface *screen, const Vector<int> &offset) const {
245 equipmentMenu.Draw(screen, offset);
248 void EquipMenu::RenderActionMenu(SDL_Surface *screen, const Vector<int> &offset) const {
249 const Font &font(*parent->Res().statusFont);
250 const Frame &frame(*parent->Res().statusFrame);
251 const Vector<int> menuOffset(3 * font.CharWidth(), font.CharHeight() + font.CharHeight() / 2);
253 frame.Draw(screen, offset, 15 * font.CharWidth(), 10 * font.CharHeight());
254 actionMenu.Draw(screen, offset + menuOffset);
257 void EquipMenu::RenderInventoryMenu(SDL_Surface *screen, const Vector<int> &offset) const {
258 const Font &font(*parent->Res().normalFont);
259 const Frame &frame(*parent->Res().statusFrame);
260 const Vector<int> menuOffset(3 * font.CharWidth(), font.CharHeight() + font.CharHeight() / 4);
262 frame.Draw(screen, offset, 30 * font.CharWidth(), 11 * font.CharHeight());
263 inventoryMenu.Draw(screen, offset + menuOffset);
267 void EquipMenu::NextHero() {
268 cursor = (cursor + 1) % parent->Game().state->partySize;
270 if (InventoryVisible()) {
275 void EquipMenu::PreviousHero() {
276 cursor = (cursor + parent->Game().state->partySize - 1) % parent->Game().state->partySize;
278 if (InventoryVisible()) {
283 Hero &EquipMenu::GetHero() {
284 return *parent->Game().state->party[cursor];
287 const Hero &EquipMenu::GetHero() const {
288 return *parent->Game().state->party[cursor];
292 void EquipMenu::LoadEquipment() {
293 equipmentMenu.Clear();
294 for (int i = 0; i < Hero::EQUIP_COUNT; ++i) {
295 if (GetHero().Equipped(Hero::EquipSlot(i))) {
296 const Item *item(GetHero().Equipment(Hero::EquipSlot(i)));
297 equipmentMenu.Add(item->Name(), item, true, item->MenuIcon());
299 equipmentMenu.Add(parent->Res().noEquipmentText, 0);
304 void EquipMenu::RemoveAllEquipment() {
305 Inventory &inv(parent->Game().state->inventory);
306 for (int i = 0; i < Hero::EQUIP_COUNT; ++i) {
307 if (GetHero().Equipped(Hero::EquipSlot(i))
308 && inv.Add(GetHero().Equipment(Hero::EquipSlot(i)), 1)) {
309 GetHero().RemoveEquipment(Hero::EquipSlot(i));
315 void EquipMenu::RemoveItem() {
316 Inventory &inv(parent->Game().state->inventory);
317 Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
319 if (GetHero().Equipped(slot) && inv.Add(GetHero().Equipment(slot), 1)) {
320 GetHero().RemoveEquipment(slot);
326 void EquipMenu::DropItem() {
327 GetHero().RemoveEquipment(Hero::EquipSlot(equipmentMenu.SelectedIndex()));
332 bool EquipMenu::InventoryVisible() const {
333 return !actionMenu.IsActive() && actionMenu.Selected() == CHOICE_EQUIP;
336 void EquipMenu::LoadInventory() {
337 const Inventory &inv = parent->Game().state->inventory;
338 const Hero &hero = GetHero();
339 const Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
341 inventoryMenu.Clear();
342 for (int i = 0; i < inv.MaxItems(); ++i) {
343 const Item *item = inv.ItemAt(i);
344 if (item && item->EquipableAt(slot)) {
345 inventoryMenu.Add(item->Name(), item, hero.CanEquip(*item),
346 item->MenuIcon(), inv.ItemCountAt(i));
351 void EquipMenu::EquipSelected() {
352 Inventory &inv = parent->Game().state->inventory;
353 Hero &hero = GetHero();
354 const Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
356 const Item *selected = inventoryMenu.Selected();
357 const Item *equipped = equipmentMenu.Selected();
359 if (!hero.CanEquip(*selected)) {
360 // TODO: error noise and blur
364 inv.Remove(selected, 1);
365 if (!inv.Add(equipped, 1)) {
367 inv.Add(selected, 1);
368 // TODO: error noise, blur, message?
372 hero.SetEquipment(slot, selected);