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"
19 using common::Inventory;
22 using geometry::Vector;
24 using graphics::Frame;
28 EquipMenu::EquipMenu(PartyMenu *parent, int cursor)
31 , actionMenu(*parent->Res().equipmentActionMenuProperties)
32 , equipmentMenu(*parent->Res().equipmentMenuProperties)
33 , inventoryMenu(*parent->Res().inventoryMenuProperties) {
34 actionMenu.Add(parent->Res().equipMenuEquipLabel, CHOICE_EQUIP);
35 actionMenu.Add(parent->Res().equipMenuStrongestLabel, CHOICE_STRONGEST);
36 actionMenu.Add(parent->Res().equipMenuRemoveLabel, CHOICE_REMOVE);
37 actionMenu.Add(parent->Res().equipMenuRemoveAllLabel, CHOICE_REMOVE_ALL);
38 actionMenu.Add(parent->Res().equipMenuDropLabel, CHOICE_DROP);
44 void EquipMenu::OnEnterState(SDL_Surface *) {
45 equipmentMenu.SetInactive();
46 inventoryMenu.SetInactive();
49 void EquipMenu::OnExitState(SDL_Surface *) {
53 void EquipMenu::OnResumeState(SDL_Surface *) {
57 void EquipMenu::OnPauseState(SDL_Surface *) {
62 void EquipMenu::OnResize(int width, int height) {
67 void EquipMenu::HandleEvents(const Input &input) {
68 if (input.JustPressed(Input::SHOULDER_LEFT)) {
71 if (input.JustPressed(Input::SHOULDER_RIGHT)) {
74 if (actionMenu.IsActive()) {
75 if (input.JustPressed(Input::PAD_UP)) {
76 actionMenu.PreviousRow();
78 if (input.JustPressed(Input::PAD_DOWN)) {
81 if (input.JustPressed(Input::ACTION_A)) {
82 switch (actionMenu.Selected()) {
85 actionMenu.SetSelected();
86 equipmentMenu.SetActive();
88 case CHOICE_STRONGEST:
89 // TODO: implement "equip strongest" when items' stat effects are done
92 actionMenu.SetSelected();
93 equipmentMenu.SetActive();
95 case CHOICE_REMOVE_ALL:
99 actionMenu.SetSelected();
100 equipmentMenu.SetActive();
103 } else if (input.JustPressed(Input::ACTION_B)) {
106 } else if (equipmentMenu.IsActive()) {
107 if (input.JustPressed(Input::PAD_UP)) {
108 equipmentMenu.PreviousRow();
109 if (InventoryVisible()) {
113 if (input.JustPressed(Input::PAD_DOWN)) {
114 equipmentMenu.NextRow();
115 if (InventoryVisible()) {
119 if (input.JustPressed(Input::ACTION_B)) {
120 equipmentMenu.SetInactive();
121 actionMenu.SetActive();
122 } else if (input.JustPressed(Input::ACTION_A)) {
123 switch (actionMenu.Selected()) {
125 equipmentMenu.SetSelected();
126 inventoryMenu.SetActive();
128 case CHOICE_STRONGEST:
129 case CHOICE_REMOVE_ALL:
130 // invalid state, recover
131 equipmentMenu.SetInactive();
132 actionMenu.SetActive();
143 if (input.JustPressed(Input::PAD_UP)) {
144 inventoryMenu.PreviousRow();
146 if (input.JustPressed(Input::PAD_DOWN)) {
147 inventoryMenu.NextRow();
149 if (input.JustPressed(Input::ACTION_A)) {
151 inventoryMenu.SetInactive();
152 equipmentMenu.SetActive();
153 } else if (input.JustPressed(Input::ACTION_B)) {
154 inventoryMenu.SetInactive();
155 equipmentMenu.SetActive();
160 void EquipMenu::UpdateWorld(float deltaT) {
164 void EquipMenu::Render(SDL_Surface *screen) {
165 Vector<int> offset((screen->w - Width()) / 2, (screen->h - Height()) / 2);
166 Vector<int> shoulderNavOffset(
167 5 * parent->Res().statusFont->CharWidth(),
168 parent->Res().statusFont->CharHeight());
169 Vector<int> statsOffset(
170 4 * parent->Res().statusFont->CharWidth(),
171 8 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
172 Vector<int> equipOffset(
173 17 * parent->Res().statusFont->CharWidth(),
174 4 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
176 parent->RenderBackground(screen);
177 parent->Res().shoulderNav->Draw(screen, offset + shoulderNavOffset);
178 RenderStatus(screen, offset + parent->StatusOffset(0));
179 RenderStats(screen, offset + statsOffset);
180 RenderEquipmentMenu(screen, offset + equipOffset);
181 if (InventoryVisible()) {
182 Vector<int> inventoryOffset(
183 parent->Res().statusFont->CharWidth(),
184 17 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
185 RenderInventoryMenu(screen, offset + inventoryOffset);
187 Vector<int> menuOffset(
188 15 * parent->Res().statusFont->CharWidth(),
189 17 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
190 RenderActionMenu(screen, offset + menuOffset);
194 int EquipMenu::Width() const {
195 return parent->Width();
198 int EquipMenu::Height() const {
199 return parent->Height();
202 void EquipMenu::RenderStatus(SDL_Surface *screen, const Vector<int> &offset) const {
203 parent->GetHeroStatus(cursor).Render(screen, offset);
206 void EquipMenu::RenderStats(SDL_Surface *screen, const Vector<int> &offset) const {
207 const Stats &stats(GetHero().GetStats());
208 Vector<int> lineBreak(0, parent->Res().statusFont->CharHeight());
210 Vector<int> position(offset);
211 RenderStatsLine(parent->Res().atpLabel, stats.Attack(), screen, position);
213 position += lineBreak;
214 RenderStatsLine(parent->Res().dfpLabel, stats.Defense(), screen, position);
216 position += lineBreak;
217 RenderStatsLine(parent->Res().strLabel, stats.Strength(), screen, position);
219 position += lineBreak;
220 RenderStatsLine(parent->Res().aglLabel, stats.Agility(), screen, position);
222 position += lineBreak;
223 RenderStatsLine(parent->Res().intLabel, stats.Intelligence(), screen, position);
225 position += lineBreak;
226 RenderStatsLine(parent->Res().gutLabel, stats.Gut(), screen, position);
228 position += lineBreak;
229 RenderStatsLine(parent->Res().mgrLabel, stats.MagicResistance(), screen, position);
232 void EquipMenu::RenderStatsLine(const char *label, int number, SDL_Surface *screen, const Vector<int> &position) const {
233 const Font &font(*parent->Res().statusFont);
234 const Vector<int> numberOffset(4 * font.CharWidth(), 0);
236 font.DrawString(label, screen, position, 3);
237 font.DrawNumber(number, screen, position + numberOffset, 3);
240 void EquipMenu::RenderEquipmentMenu(SDL_Surface *screen, const Vector<int> &offset) const {
241 equipmentMenu.Draw(screen, offset);
244 void EquipMenu::RenderActionMenu(SDL_Surface *screen, const Vector<int> &offset) const {
245 const Font &font(*parent->Res().statusFont);
246 const Frame &frame(*parent->Res().statusFrame);
247 const Vector<int> menuOffset(3 * font.CharWidth(), font.CharHeight() + font.CharHeight() / 2);
249 frame.Draw(screen, offset, 15 * font.CharWidth(), 10 * font.CharHeight());
250 actionMenu.Draw(screen, offset + menuOffset);
253 void EquipMenu::RenderInventoryMenu(SDL_Surface *screen, const Vector<int> &offset) const {
254 const Font &font(*parent->Res().normalFont);
255 const Frame &frame(*parent->Res().statusFrame);
256 const Vector<int> menuOffset(3 * font.CharWidth(), font.CharHeight() + font.CharHeight() / 4);
258 frame.Draw(screen, offset, 30 * font.CharWidth(), 11 * font.CharHeight());
259 inventoryMenu.Draw(screen, offset + menuOffset);
263 void EquipMenu::NextHero() {
264 cursor = (cursor + 1) % parent->Game().state->partySize;
266 if (InventoryVisible()) {
271 void EquipMenu::PreviousHero() {
272 cursor = (cursor + parent->Game().state->partySize - 1) % parent->Game().state->partySize;
274 if (InventoryVisible()) {
279 Hero &EquipMenu::GetHero() {
280 return *parent->Game().state->party[cursor];
283 const Hero &EquipMenu::GetHero() const {
284 return *parent->Game().state->party[cursor];
288 void EquipMenu::LoadEquipment() {
289 equipmentMenu.Clear();
290 for (int i = 0; i < Hero::EQUIP_COUNT; ++i) {
291 if (GetHero().Equipped(Hero::EquipSlot(i))) {
292 const Item *item(GetHero().Equipment(Hero::EquipSlot(i)));
293 equipmentMenu.Add(item->Name(), item, true, item->MenuIcon());
295 equipmentMenu.Add(parent->Res().noEquipmentText, 0);
300 void EquipMenu::RemoveAllEquipment() {
301 Inventory &inv(parent->Game().state->inventory);
302 for (int i = 0; i < Hero::EQUIP_COUNT; ++i) {
303 if (GetHero().Equipped(Hero::EquipSlot(i))
304 && inv.Add(GetHero().Equipment(Hero::EquipSlot(i)), 1)) {
305 GetHero().RemoveEquipment(Hero::EquipSlot(i));
311 void EquipMenu::RemoveItem() {
312 Inventory &inv(parent->Game().state->inventory);
313 Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
315 if (GetHero().Equipped(slot) && inv.Add(GetHero().Equipment(slot), 1)) {
316 GetHero().RemoveEquipment(slot);
322 void EquipMenu::DropItem() {
323 GetHero().RemoveEquipment(Hero::EquipSlot(equipmentMenu.SelectedIndex()));
328 bool EquipMenu::InventoryVisible() const {
329 return !actionMenu.IsActive() && actionMenu.Selected() == CHOICE_EQUIP;
332 void EquipMenu::LoadInventory() {
333 const Inventory &inv = parent->Game().state->inventory;
334 const Hero &hero = GetHero();
335 const Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
337 inventoryMenu.Clear();
338 for (int i = 0; i < inv.MaxItems(); ++i) {
339 const Item *item = inv.ItemAt(i);
340 if (item && item->EquipableAt(slot)) {
341 inventoryMenu.Add(item->Name(), item, hero.CanEquip(*item),
342 item->MenuIcon(), inv.ItemCountAt(i));
347 void EquipMenu::EquipSelected() {
348 Inventory &inv = parent->Game().state->inventory;
349 Hero &hero = GetHero();
350 const Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
352 const Item *selected = inventoryMenu.Selected();
353 const Item *equipped = equipmentMenu.Selected();
355 if (!hero.CanEquip(*selected)) {
356 // TODO: error noise and blur
360 inv.Remove(selected, 1);
361 if (!inv.Add(equipped, 1)) {
363 inv.Add(selected, 1);
364 // TODO: error noise, blur, message?
368 hero.SetEquipment(slot, selected);