]> git.localhorst.tv Git - l2e.git/blobdiff - src/menu/EquipMenu.cpp
switched geometric scalars from floating to fixed
[l2e.git] / src / menu / EquipMenu.cpp
index da24f771f10723d342f00ea97fddf1f8fda58181..8e509660ee302a81b50e457712dfbb3c60581fd0 100644 (file)
@@ -1,10 +1,3 @@
-/*
- * EquipMenu.cpp
- *
- *  Created on: Nov 18, 2012
- *      Author: holy
- */
-
 #include "EquipMenu.h"
 
 #include "HeroStatus.h"
@@ -15,6 +8,7 @@
 #include "../common/GameConfig.h"
 #include "../common/GameState.h"
 #include "../common/Hero.h"
+#include "../common/Inventory.h"
 #include "../common/Item.h"
 #include "../common/Stats.h"
 #include "../graphics/Font.h"
 
 using app::Input;
 using common::Hero;
+using common::Inventory;
 using common::Item;
 using common::Stats;
-using geometry::Vector;
+using math::Vector;
 using graphics::Font;
 using graphics::Frame;
 
@@ -48,6 +43,7 @@ EquipMenu::EquipMenu(PartyMenu *parent, int cursor)
 
 void EquipMenu::OnEnterState(SDL_Surface *) {
        equipmentMenu.SetInactive();
+       inventoryMenu.SetInactive();
 }
 
 void EquipMenu::OnExitState(SDL_Surface *) {
@@ -69,10 +65,99 @@ void EquipMenu::OnResize(int width, int height) {
 
 
 void EquipMenu::HandleEvents(const Input &input) {
-
+       if (input.JustPressed(Input::SHOULDER_LEFT)) {
+               PreviousHero();
+       }
+       if (input.JustPressed(Input::SHOULDER_RIGHT)) {
+               NextHero();
+       }
+       if (actionMenu.IsActive()) {
+               if (input.JustPressed(Input::PAD_UP)) {
+                       actionMenu.PreviousRow();
+               }
+               if (input.JustPressed(Input::PAD_DOWN)) {
+                       actionMenu.NextRow();
+               }
+               if (input.JustPressed(Input::ACTION_A)) {
+                       switch (actionMenu.Selected()) {
+                               case CHOICE_EQUIP:
+                                       LoadEquipment();
+                                       actionMenu.SetSelected();
+                                       equipmentMenu.SetActive();
+                                       break;
+                               case CHOICE_STRONGEST:
+                                       // TODO: implement "equip strongest" when items' stat effects are done
+                                       break;
+                               case CHOICE_REMOVE:
+                                       actionMenu.SetSelected();
+                                       equipmentMenu.SetActive();
+                                       break;
+                               case CHOICE_REMOVE_ALL:
+                                       RemoveAllEquipment();
+                                       break;
+                               case CHOICE_DROP:
+                                       actionMenu.SetSelected();
+                                       equipmentMenu.SetActive();
+                                       break;
+                       }
+               } else if (input.JustPressed(Input::ACTION_B)) {
+                       Ctrl().PopState();
+               }
+       } else if (equipmentMenu.IsActive()) {
+               if (input.JustPressed(Input::PAD_UP)) {
+                       equipmentMenu.PreviousRow();
+                       if (InventoryVisible()) {
+                               LoadInventory();
+                       }
+               }
+               if (input.JustPressed(Input::PAD_DOWN)) {
+                       equipmentMenu.NextRow();
+                       if (InventoryVisible()) {
+                               LoadInventory();
+                       }
+               }
+               if (input.JustPressed(Input::ACTION_B)) {
+                       equipmentMenu.SetInactive();
+                       actionMenu.SetActive();
+               } else if (input.JustPressed(Input::ACTION_A)) {
+                       switch (actionMenu.Selected()) {
+                               case CHOICE_EQUIP:
+                                       equipmentMenu.SetSelected();
+                                       inventoryMenu.SetActive();
+                                       break;
+                               case CHOICE_STRONGEST:
+                               case CHOICE_REMOVE_ALL:
+                                       // invalid state, recover
+                                       equipmentMenu.SetInactive();
+                                       actionMenu.SetActive();
+                                       break;
+                               case CHOICE_REMOVE:
+                                       RemoveItem();
+                                       break;
+                               case CHOICE_DROP:
+                                       DropItem();
+                                       break;
+                       }
+               }
+       } else {
+               if (input.JustPressed(Input::PAD_UP)) {
+                       inventoryMenu.PreviousRow();
+               }
+               if (input.JustPressed(Input::PAD_DOWN)) {
+                       inventoryMenu.NextRow();
+               }
+               if (input.JustPressed(Input::ACTION_A)) {
+                       EquipSelected();
+                       inventoryMenu.SetInactive();
+                       equipmentMenu.SetActive();
+               } else if (input.JustPressed(Input::ACTION_B)) {
+                       inventoryMenu.SetInactive();
+                       equipmentMenu.SetActive();
+               }
+       }
 }
 
-void EquipMenu::UpdateWorld(float deltaT) {
+void EquipMenu::UpdateWorld(Uint32 deltaT) {
 
 }
 
@@ -92,7 +177,18 @@ void EquipMenu::Render(SDL_Surface *screen) {
        parent->Res().shoulderNav->Draw(screen, offset + shoulderNavOffset);
        RenderStatus(screen, offset + parent->StatusOffset(0));
        RenderStats(screen, offset + statsOffset);
-       RenderEquipmentMenu(screen, equipOffset);
+       RenderEquipmentMenu(screen, offset + equipOffset);
+       if (InventoryVisible()) {
+               Vector<int> inventoryOffset(
+                               parent->Res().statusFont->CharWidth(),
+                               17 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
+               RenderInventoryMenu(screen, offset + inventoryOffset);
+       } else {
+               Vector<int> menuOffset(
+                               15 * parent->Res().statusFont->CharWidth(),
+                               17 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8);
+               RenderActionMenu(screen, offset + menuOffset);
+       }
 }
 
 int EquipMenu::Width() const {
@@ -146,36 +242,132 @@ void EquipMenu::RenderEquipmentMenu(SDL_Surface *screen, const Vector<int> &offs
 }
 
 void EquipMenu::RenderActionMenu(SDL_Surface *screen, const Vector<int> &offset) const {
+       const Font &font(*parent->Res().statusFont);
+       const Frame &frame(*parent->Res().statusFrame);
+       const Vector<int> menuOffset(3 * font.CharWidth(), font.CharHeight() + font.CharHeight() / 2);
 
+       frame.Draw(screen, offset, 15 * font.CharWidth(), 10 * font.CharHeight());
+       actionMenu.Draw(screen, offset + menuOffset);
 }
 
 void EquipMenu::RenderInventoryMenu(SDL_Surface *screen, const Vector<int> &offset) const {
+       const Font &font(*parent->Res().normalFont);
+       const Frame &frame(*parent->Res().statusFrame);
+       const Vector<int> menuOffset(3 * font.CharWidth(), font.CharHeight() + font.CharHeight() / 4);
 
+       frame.Draw(screen, offset, 30 * font.CharWidth(), 11 * font.CharHeight());
+       inventoryMenu.Draw(screen, offset + menuOffset);
 }
 
 
 void EquipMenu::NextHero() {
        cursor = (cursor + 1) % parent->Game().state->partySize;
        LoadEquipment();
+       if (InventoryVisible()) {
+               LoadInventory();
+       }
 }
 
 void EquipMenu::PreviousHero() {
        cursor = (cursor + parent->Game().state->partySize - 1) % parent->Game().state->partySize;
        LoadEquipment();
+       if (InventoryVisible()) {
+               LoadInventory();
+       }
+}
+
+Hero &EquipMenu::GetHero() {
+       return *parent->Game().state->party[cursor];
 }
 
 const Hero &EquipMenu::GetHero() const {
        return *parent->Game().state->party[cursor];
 }
 
+
 void EquipMenu::LoadEquipment() {
        equipmentMenu.Clear();
-       equipmentMenu.Add(GetHero().Weapon()->Name(), GetHero().Weapon(), true, GetHero().Weapon()->MenuIcon());
-       equipmentMenu.Add(GetHero().Armor()->Name(), GetHero().Armor(), true, GetHero().Armor()->MenuIcon());
-       equipmentMenu.Add(GetHero().Shield()->Name(), GetHero().Shield(), true, GetHero().Shield()->MenuIcon());
-       equipmentMenu.Add(GetHero().Helmet()->Name(), GetHero().Helmet(), true, GetHero().Helmet()->MenuIcon());
-       equipmentMenu.Add(GetHero().Ring()->Name(), GetHero().Ring(), true, GetHero().Ring()->MenuIcon());
-       equipmentMenu.Add(GetHero().Jewel()->Name(), GetHero().Jewel(), true, GetHero().Jewel()->MenuIcon());
+       for (int i = 0; i < Hero::EQUIP_COUNT; ++i) {
+               if (GetHero().Equipped(Hero::EquipSlot(i))) {
+                       const Item *item(GetHero().Equipment(Hero::EquipSlot(i)));
+                       equipmentMenu.Add(item->Name(), item, true, item->MenuIcon());
+               } else {
+                       equipmentMenu.Add(parent->Res().noEquipmentText, 0);
+               }
+       }
+}
+
+void EquipMenu::RemoveAllEquipment() {
+       Inventory &inv(parent->Game().state->inventory);
+       for (int i = 0; i < Hero::EQUIP_COUNT; ++i) {
+               if (GetHero().Equipped(Hero::EquipSlot(i))
+                               && inv.Add(GetHero().Equipment(Hero::EquipSlot(i)), 1)) {
+                       GetHero().RemoveEquipment(Hero::EquipSlot(i));
+               }
+       }
+       LoadEquipment();
+}
+
+void EquipMenu::RemoveItem() {
+       Inventory &inv(parent->Game().state->inventory);
+       Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
+
+       if (GetHero().Equipped(slot) && inv.Add(GetHero().Equipment(slot), 1)) {
+               GetHero().RemoveEquipment(slot);
+       }
+
+       LoadEquipment();
+}
+
+void EquipMenu::DropItem() {
+       GetHero().RemoveEquipment(Hero::EquipSlot(equipmentMenu.SelectedIndex()));
+       LoadEquipment();
+}
+
+
+bool EquipMenu::InventoryVisible() const {
+       return !actionMenu.IsActive() && actionMenu.Selected() == CHOICE_EQUIP;
+}
+
+void EquipMenu::LoadInventory() {
+       const Inventory &inv = parent->Game().state->inventory;
+       const Hero &hero = GetHero();
+       const Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
+
+       inventoryMenu.Clear();
+       for (int i = 0; i < inv.MaxItems(); ++i) {
+               const Item *item = inv.ItemAt(i);
+               if (item && item->EquipableAt(slot)) {
+                       inventoryMenu.Add(item->Name(), item, hero.CanEquip(*item),
+                                       item->MenuIcon(), inv.ItemCountAt(i));
+               }
+       }
+}
+
+void EquipMenu::EquipSelected() {
+       Inventory &inv = parent->Game().state->inventory;
+       Hero &hero = GetHero();
+       const Hero::EquipSlot slot = Hero::EquipSlot(equipmentMenu.SelectedIndex());
+
+       const Item *selected = inventoryMenu.Selected();
+       const Item *equipped = equipmentMenu.Selected();
+
+       if (!hero.CanEquip(*selected)) {
+               // TODO: error noise and blur
+               return;
+       }
+
+       inv.Remove(selected, 1);
+       if (!inv.Add(equipped, 1)) {
+               // roll back
+               inv.Add(selected, 1);
+               // TODO: error noise, blur, message?
+               return;
+       }
+
+       hero.SetEquipment(slot, selected);
+       LoadEquipment();
+       LoadInventory();
 }
 
 }