15 constexpr glm::vec2 BoxTitlePosition(365.f, 70.f);
16 constexpr glm::vec2 BoxTitleSize(701.f - BoxTitlePosition.x, 130.f - BoxTitlePosition.y);
17 constexpr glm::vec2 ThumbnailPosition(68.f, 284.f);
18 constexpr glm::vec2 ThumbnailSize(218.f - ThumbnailPosition.x, 434.f - ThumbnailPosition.y);
19 constexpr glm::vec2 NamePosition(ThumbnailPosition.x + ThumbnailSize.x * 0.5f,
20 ThumbnailPosition.y + ThumbnailSize.y + 4.f);
21 constexpr glm::vec2 LevelPosition(ThumbnailPosition.x + 4.f, 475.f);
22 constexpr glm::vec2 ItemLabelPosition(LevelPosition.x, LevelPosition.y + 36.f);
23 constexpr glm::vec2 ItemPosition(ItemLabelPosition.x, ItemLabelPosition.y + 25.f);
24 constexpr
float SlideTime = 0.5f;
33 :
State(s,
bl::engine::StateMask::Menu)
34 , state(MenuState::ChooseAction)
38 , activeGrid(&grids[0])
39 , slidingOutGrid(&grids[1])
42 , depositedPeoplemon(-1) {
43 auto joinPath = bl::util::FileUtil::joinPath;
45 using bl::menu::TextItem;
48 actionMenu.create(s.
engine(),
49 s.
engine().renderer().getObserver(),
50 bl::menu::ArrowSelector::create(12.f, sf::Color::Black));
51 contextMenu.create(s.
engine(),
52 s.
engine().renderer().getObserver(),
53 bl::menu::ArrowSelector::create(12.f, sf::Color::Black));
55 backgroundTxtr = s.
engine().renderer().texturePool().getOrLoadTexture(
56 joinPath(Properties::MenuImagePath(),
"StorageSystem/storageBGND.png"));
57 background.create(s.
engine(), backgroundTxtr);
58 grids[0].activate(background.entity());
59 grids[1].activate(background.entity());
61 leftArrowTxtr = s.
engine().renderer().texturePool().getOrLoadTexture(
62 joinPath(Properties::MenuImagePath(),
"StorageSystem/storageArrowLeft.png"));
63 leftArrow.create(s.
engine(), leftArrowTxtr);
64 leftArrow.getTransform().setPosition(BoxTitlePosition.x - leftArrowTxtr->size().x - 3.f,
65 BoxTitlePosition.y + BoxTitleSize.y * 0.5f -
66 leftArrowTxtr->size().y * 0.5f);
67 leftArrow.setParent(background);
69 rightArrowTxtr = s.
engine().renderer().texturePool().getOrLoadTexture(
70 joinPath(Properties::MenuImagePath(),
"StorageSystem/storageArrowRight.png"));
71 rightArrow.create(s.
engine(), rightArrowTxtr);
72 rightArrow.getTransform().setPosition(BoxTitlePosition.x + BoxTitleSize.x + 3.f,
73 BoxTitlePosition.y + BoxTitleSize.y * 0.5f -
74 rightArrowTxtr->size().y * 0.5f);
75 rightArrow.setParent(background);
78 boxTitle.getTransform().setPosition(BoxTitlePosition + BoxTitleSize * 0.5f);
79 boxTitle.setParent(background);
82 nickname.getTransform().setPosition(NamePosition);
83 nickname.setParent(background);
86 level.getTransform().setPosition(LevelPosition);
87 level.setParent(background);
91 itemLabel.addSection(
"", 16, sf::Color(165, 255, 255));
92 itemLabel.getTransform().setPosition(ItemLabelPosition);
93 itemLabel.setParent(background);
95 TextItem::Ptr depositItem =
96 TextItem::create(
"Deposit", Properties::MenuFont(), sf::Color::Black, 34);
97 depositItem->getSignal(Item::Activated)
98 .willAlwaysCall(std::bind(&StorageSystem::startDeposit,
this));
99 withdrawActionItem = TextItem::create(
"Browse", Properties::MenuFont(), sf::Color::Black, 34);
100 withdrawActionItem->getSignal(Item::Activated)
101 .willAlwaysCall(std::bind(&StorageSystem::startBrowse,
this));
102 TextItem::Ptr closeItem =
103 TextItem::create(
"Close", Properties::MenuFont(), sf::Color::Black, 34);
104 closeItem->getSignal(Item::Activated).willAlwaysCall(std::bind(&StorageSystem::close,
this));
105 actionMenu.setRootItem(withdrawActionItem);
106 actionMenu.addItem(depositItem, withdrawActionItem.get(), Item::Bottom);
107 actionMenu.addItem(closeItem, depositItem.get(), Item::Bottom);
108 actionMenu.setPosition({30.f, 25.f});
109 actionMenu.configureBackground(sf::Color::White, sf::Color::Black, 3.f, {20.f, 2.f, 4.f, 4.f});
111 TextItem::Ptr withdrawItem = TextItem::create(
"Withdraw", Properties::MenuFont());
112 withdrawItem->getSignal(Item::Activated)
113 .willAlwaysCall(std::bind(&StorageSystem::onWithdraw,
this));
114 TextItem::Ptr moveItem = TextItem::create(
"Move", Properties::MenuFont());
115 moveItem->getSignal(Item::Activated)
116 .willAlwaysCall(std::bind(&StorageSystem::onStartMove,
this));
117 TextItem::Ptr itemItem = TextItem::create(
"Take Item", Properties::MenuFont());
118 itemItem->getSignal(Item::Activated)
119 .willAlwaysCall(std::bind(&StorageSystem::onTakeItem,
this));
120 TextItem::Ptr releaseItem = TextItem::create(
"Release", Properties::MenuFont());
121 releaseItem->getSignal(Item::Activated)
122 .willAlwaysCall(std::bind(&StorageSystem::onRelease,
this));
123 TextItem::Ptr backItem = TextItem::create(
"Back", Properties::MenuFont());
124 backItem->getSignal(Item::Activated)
125 .willAlwaysCall(std::bind(&StorageSystem::onCloseContextMenu,
this));
126 contextMenu.setRootItem(withdrawItem);
127 contextMenu.addItem(moveItem, withdrawItem.get(), Item::Bottom);
128 contextMenu.addItem(itemItem, moveItem.get(), Item::Bottom);
129 contextMenu.addItem(releaseItem, itemItem.get(), Item::Bottom);
130 contextMenu.addItem(backItem, releaseItem.get(), Item::Bottom);
131 contextMenu.configureBackground(sf::Color::White, sf::Color::Black, 2.f, {20.f, 2.f, 4.f, 4.f});
134 pageSlideSound = bl::audio::AudioSystem::getOrLoadSound(
135 joinPath(Properties::SoundPath(),
"Menu/storageBoxChange.mp3"));
136 cursorMoveSound = bl::audio::AudioSystem::getOrLoadSound(
137 joinPath(Properties::SoundPath(),
"Menu/storageCursorMove.mp3"));
140 const char* StorageSystem::name()
const {
return "StorageSystem"; }
142 void StorageSystem::activate(bl::engine::Engine& engine) {
143 systems.engine().inputSystem().getActor().addListener(*
this);
145 overlay = engine.renderer().getObserver().pushScene<bl::rc::Overlay>();
146 background.addToScene(overlay, bl::rc::UpdateSpeed::Static);
147 leftArrow.addToScene(overlay, bl::rc::UpdateSpeed::Static);
148 rightArrow.addToScene(overlay, bl::rc::UpdateSpeed::Static);
149 boxTitle.addToScene(overlay, bl::rc::UpdateSpeed::Static);
150 nickname.addToScene(overlay, bl::rc::UpdateSpeed::Static);
151 level.addToScene(overlay, bl::rc::UpdateSpeed::Static);
152 itemLabel.addToScene(overlay, bl::rc::UpdateSpeed::Static);
153 if (thumbnail.entity() != bl::ecs::InvalidEntity) {
154 thumbnail.addToScene(overlay, bl::rc::UpdateSpeed::Static);
156 actionMenu.addToOverlay(background.entity());
157 contextMenu.addToOverlay(background.entity());
158 cursor.activate(background.entity());
159 activeGrid->activate(background.entity());
160 slidingOutGrid->activate(background.entity());
162 hovered = systems.player().state().storage.get(currentBox, cursor.getPosition());
163 if (state == MenuState::WaitingDeposit) {
164 if (depositedPeoplemon >= 0) {
165 actionMenu.setSelectedItem(withdrawActionItem.get());
166 const auto& ppl = systems.player().state().peoplemon[depositedPeoplemon];
168 updatePeoplemonInfo(ppl);
169 cursor.setHolding(ppl.id());
170 enterState(MenuState::PlacingPeoplemon);
171 showPeoplemonInfo(
true);
174 showPeoplemonInfo(
false);
175 enterState(MenuState::ChooseAction);
179 showPeoplemonInfo(
false);
180 enterState(MenuState::ChooseAction);
184 if (hovered !=
nullptr) { updatePeoplemonInfo(hovered->peoplemon); }
186 contextMenu.setHidden(
true);
189 void StorageSystem::deactivate(bl::engine::Engine& engine) {
190 systems.engine().inputSystem().getActor().removeListener(*
this);
191 bl::event::Dispatcher::dispatch<core::event::StorageSystemClosed>({});
193 activeGrid->deactivate();
194 engine.renderer().getObserver().popScene();
198 void StorageSystem::update(bl::engine::Engine&,
float dt,
float) {
202 case MenuState::BoxSliding:
203 slideOffset += slideVel * dt;
205 std::abs(slideVel) * -1.f);
206 slidingOutGrid->notifyOffset(slideOffset);
208 slidingOutGrid->deactivate();
209 activeGrid->notifyOffset(0.f);
210 enterState(prevState);
214 case MenuState::WaitingContextMessage:
215 case MenuState::WaitingReleaseConfirm:
218 case MenuState::CursorMoving:
219 if (!cursor.moving()) { enterState(prevState); }
227 void StorageSystem::startDeposit() {
228 if (systems.player().state().peoplemon.size() > 1) {
229 systems.engine().pushState(PeoplemonMenu::create(
230 systems, PeoplemonMenu::Context::StorageSelect, -1, &depositedPeoplemon));
231 enterState(MenuState::WaitingDeposit);
234 systems.hud().displayMessage(
"You cannot deposit your last Peoplemon!",
235 std::bind(&StorageSystem::onMessageDone,
this));
236 enterState(MenuState::WaitingHudMessage);
240 void StorageSystem::startBrowse() { enterState(MenuState::BrowsingBox); }
242 void StorageSystem::close() { systems.engine().popState(); }
244 void StorageSystem::onCursor(
const sf::Vector2i& pos) {
245 if (state == MenuState::PlacingPeoplemon || state == MenuState::MovingPeoplemon)
return;
246 onHover(systems.player().state().storage.get(currentBox, pos));
251 if (ppl !=
nullptr) {
253 showPeoplemonInfo(
true);
255 else { showPeoplemonInfo(
false); }
259 nickname.getSection().setString(ppl.
name());
260 nickname.getTransform().setOrigin(nickname.getLocalBounds().width * 0.5f, 0.f);
261 level.getSection().setString(
"Level " + std::to_string(ppl.
currentLevel()));
268 void StorageSystem::updateThumbnail(
const std::string& src) {
269 thumbTxtr = systems.engine().renderer().texturePool().getOrLoadTexture(src);
270 if (thumbnail.entity() == bl::ecs::InvalidEntity) {
271 thumbnail.create(systems.engine(), thumbTxtr);
272 thumbnail.getTransform().setPosition(ThumbnailPosition);
273 thumbnail.setParent(background);
274 if (overlay) { thumbnail.addToScene(overlay, bl::rc::UpdateSpeed::Static); }
276 else { thumbnail.setTexture(thumbTxtr); }
277 thumbnail.scaleToSize(ThumbnailSize);
280 void StorageSystem::onSelect(
const sf::Vector2i& pos) {
284 case MenuState::PlacingPeoplemon:
285 if (!systems.player().state().storage.get(currentBox, pos)) {
286 systems.player().state().storage.add(
287 currentBox, pos, systems.player().state().peoplemon[depositedPeoplemon]);
288 systems.player().state().peoplemon.erase(systems.player().state().peoplemon.begin() +
290 activeGrid->update(systems.player().state().storage.getBox(currentBox));
292 enterState(MenuState::BrowsingBox);
293 onCursor(cursor.getPosition());
297 case MenuState::BrowsingBox:
298 if (hovered !=
nullptr) { enterState(MenuState::BrowseMenuOpen); }
300 case MenuState::MovingPeoplemon:
302 hovered->position = ogMovePos;
303 hovered = systems.player().state().storage.move(*hovered, currentBox, pos);
304 activeGrid->update(systems.player().state().storage.getBox(currentBox));
307 enterState(MenuState::BrowsingBox);
314 void StorageSystem::boxLeft() {
315 if (currentBox == 0)
return;
320 enterState(MenuState::BoxSliding);
323 void StorageSystem::boxRight() {
326 slideVel = -SlideVel;
329 enterState(MenuState::BoxSliding);
332 void StorageSystem::finishBoxChange() {
333 boxTitle.getSection().setString(
"Storage Box " + std::to_string(currentBox + 1));
334 boxTitle.getTransform().setOrigin(boxTitle.getLocalBounds().width * 0.5f,
335 boxTitle.getLocalBounds().height * 0.5f);
337 leftArrow.setHidden(currentBox == 0);
338 rightArrow.setHidden(currentBox == 13);
340 std::swap(activeGrid, slidingOutGrid);
341 activeGrid->update(systems.player().state().storage.getBox(currentBox));
342 activeGrid->notifyOffset(0.f);
345 void StorageSystem::showContextMessage(
const std::string& msg,
bool cm) {
346 closeMenuAfterMessage = cm;
347 systems.hud().displayMessage(msg, std::bind(&StorageSystem::onMessageDone,
this));
348 enterState(MenuState::WaitingContextMessage);
351 void StorageSystem::onWithdraw() {
352 if (systems.player().state().peoplemon.size() == 6) {
353 showContextMessage(
"Your party is full! Ditch some other loser to make room.",
false);
356 showContextMessage(hovered->peoplemon.name() +
" was added to your party!");
357 systems.player().state().peoplemon.emplace_back(hovered->peoplemon);
358 systems.player().state().storage.remove(currentBox, selectPos);
359 activeGrid->update(systems.player().state().storage.getBox(currentBox));
363 void StorageSystem::onStartMove() {
364 ogMovePos = cursor.getPosition();
365 hovered->position = {-5, -5};
366 cursor.setHolding(hovered->peoplemon.id());
367 activeGrid->update(systems.player().state().storage.getBox(currentBox));
368 enterState(MenuState::MovingPeoplemon);
371 void StorageSystem::onTakeItem() {
373 showContextMessage(hovered->peoplemon.name() +
" had their " +
375 " ripped from their hands!");
376 systems.player().state().bag.addItem(hovered->peoplemon.holdItem());
379 else { showContextMessage(hovered->peoplemon.name() +
" isn't holding anything!",
false); }
382 void StorageSystem::onRelease() {
383 systems.hud().promptUser(
384 "Are you sure you want to tell " + hovered->peoplemon.name() +
" to go away forever?",
386 std::bind(&StorageSystem::onReleaseConfirm,
this, std::placeholders::_1));
387 enterState(MenuState::WaitingReleaseConfirm);
390 void StorageSystem::onCloseContextMenu() {
392 enterState(MenuState::BrowsingBox);
395 bool StorageSystem::observe(
const bl::input::Actor&,
unsigned int cmd, bl::input::DispatchType,
396 bool eventTriggered) {
397 bl::menu::Menu* toSend =
nullptr;
399 if (!eventTriggered)
return true;
402 case MenuState::ChooseAction:
405 case MenuState::PlacingPeoplemon:
407 enterState(MenuState::ChooseAction);
409 case MenuState::BrowsingBox:
410 enterState(MenuState::ChooseAction);
412 case MenuState::MovingPeoplemon:
414 hovered->position = ogMovePos;
415 activeGrid->update(systems.player().state().storage.getBox(currentBox));
419 case MenuState::BrowseMenuOpen:
420 enterState(MenuState::BrowsingBox);
421 onCursor(cursor.getPosition());
430 case MenuState::ChooseAction:
431 toSend = &actionMenu;
434 case MenuState::PlacingPeoplemon:
435 case MenuState::BrowsingBox:
436 case MenuState::MovingPeoplemon:
438 if (eventTriggered) { onSelect(cursor.getPosition()); }
441 if (currentBox > 0) {
443 bl::audio::AudioSystem::playOrRestartSound(pageSlideSound);
445 else { bl::audio::AudioSystem::playOrRestartSound(pageSlideFailSound); }
451 bl::audio::AudioSystem::playOrRestartSound(pageSlideSound);
453 else { bl::audio::AudioSystem::playOrRestartSound(pageSlideFailSound); }
456 if (cursor.process(cmd, eventTriggered)) {
457 onCursor(cursor.getPosition());
458 bl::audio::AudioSystem::playOrRestartSound(cursorMoveSound);
459 enterState(MenuState::CursorMoving);
467 case MenuState::BrowseMenuOpen:
468 toSend = &contextMenu;
475 if (toSend !=
nullptr) {
476 menuDriver.drive(toSend);
477 menuDriver.sendControl(cmd, eventTriggered);
483 void StorageSystem::enterState(MenuState ns) {
487 cursor.setHidden(ns == MenuState::ChooseAction || ns == MenuState::BoxSliding ||
488 ns == MenuState::WaitingHudMessage);
489 contextMenu.setHidden(
true);
492 case MenuState::BrowseMenuOpen:
493 positionContextMenu();
496 case MenuState::WaitingContextMessage:
497 case MenuState::WaitingReleaseConfirm:
498 contextMenu.setHidden(
false);
504 if (hovered !=
nullptr) { updatePeoplemonInfo(hovered->peoplemon); }
507 void StorageSystem::onReleaseConfirm(
const std::string& c) {
509 showContextMessage(hovered->peoplemon.name() +
510 " was released and will probably end up on the streets.");
511 systems.player().state().storage.remove(currentBox, selectPos);
512 activeGrid->update(systems.player().state().storage.getBox(currentBox));
514 else { enterState(MenuState::BrowseMenuOpen); }
517 void StorageSystem::onMessageDone() {
519 case MenuState::WaitingContextMessage:
520 enterState(closeMenuAfterMessage ? MenuState::BrowsingBox : MenuState::BrowseMenuOpen);
521 onCursor(cursor.getPosition());
523 case MenuState::WaitingHudMessage:
524 enterState(MenuState::ChooseAction);
529 void StorageSystem::showPeoplemonInfo(
bool s) {
530 const bool hidden = !s;
531 nickname.setHidden(hidden);
532 level.setHidden(hidden);
533 itemLabel.setHidden(hidden);
536 "StorageSystem/question.png"));
540 void StorageSystem::positionContextMenu() {
541 constexpr
float Padding = 5.f;
543 glm::vec2 pos(cursor.getPosition().x + 1, cursor.getPosition().y + 1);
553 contextMenu.setPosition(pos);
Parent namespace for all functionality unique to the game.
static const std::string & getName(item::Id item)
Returns the name of the given item.
Represents an instance of a peoplemon. Can be a wild peoplemon, trainer, or player peoplemon....
unsigned int currentLevel() const
Returns the current level of this peoplemon.
Id id() const
Returns the id of this peoplemon.
item::Id & holdItem()
Access the current hold item of this peoplemon.
const std::string & name() const
Returns the name of this peoplemon, custom or defualt.
static std::string thumbnailImage(Id id)
Returns the path of the image to render as the peoplemon thumbnail.
Represents a Peoplemon in storage.
OwnedPeoplemon peoplemon
The peoplemon itself.
static constexpr int BoxCount
static constexpr int BoxWidth
Wrapper around bl::engine::Configuration. Provides application configuration in variables that may be...
static bl::audio::AudioSystem::Handle MenuMoveFailSound()
static const sf::VulkanFont & MenuFont()
static bl::audio::AudioSystem::Handle MenuBackSound()
static const std::string & MenuImagePath()
static sf::Vector2f WindowSize()
Owns all primary systems and a reference to the engine.
const bl::engine::Engine & engine() const
Const accessor for the Engine.
static float TileSize()
Returns the size of a square on the grid.
static constexpr glm::vec2 BoxPosition
static constexpr glm::vec2 BoxSize
Parent to all game states. Provides some commonly required data like core game systems.
Game state for the peoplemon storage system menu.
static bl::engine::State::Ptr create(core::system::Systems &systems)
Create a new storage system menu.