Peoplemon  0.1.0
Peoplemon 3 game source documentation
PlayerMenu.cpp
Go to the documentation of this file.
2 
3 #include <BLIB/Audio/AudioSystem.hpp>
7 #include <Core/Properties.hpp>
8 #include <Core/Resources.hpp>
9 
10 namespace core
11 {
12 namespace battle
13 {
14 namespace view
15 {
16 namespace
17 {
18 constexpr glm::vec2 MoveBoxPos(499.f, 463.f);
19 }
20 
21 PlayerMenu::PlayerMenu(bl::engine::Engine& engine, bool canRun)
22 : engine(engine)
23 , canRun(canRun)
24 , state(State::Hidden)
25 , stateLoopGuard(false)
26 , currentPeoplemon(0)
27 , actionMenu(0.f)
28 , moveMenu(0.f)
29 , moves(nullptr) {}
30 
31 void PlayerMenu::init(bl::rc::scene::CodeScene* scene) {
32  using namespace bl::menu;
33 
34  actionMenu.create(engine,
35  engine.renderer().getObserver(),
36  bl::menu::ArrowSelector::create(12.f, sf::Color::Black));
37  actionMenu.addToScene(scene);
38 
39  moveMenu.create(engine,
40  engine.renderer().getObserver(),
41  bl::menu::ArrowSelector::create(12.f, sf::Color::Black));
42  moveMenu.addToScene(scene);
43 
44  fightItem = TextItem::create("Fight", Properties::MenuFont(), sf::Color::Black, 30);
45  fightItem->getSignal(Item::Activated).willAlwaysCall(std::bind(&PlayerMenu::fightChosen, this));
46  bagItem = TextItem::create("Bag", Properties::MenuFont(), sf::Color::Black, 30);
47  bagItem->getSignal(Item::Activated).willAlwaysCall(std::bind(&PlayerMenu::itemChosen, this));
48  switchItem = TextItem::create("Switch", Properties::MenuFont(), sf::Color::Black, 30);
49  switchItem->getSignal(Item::Activated)
50  .willAlwaysCall(std::bind(&PlayerMenu::switchChosen, this));
51  runItem = TextItem::create("Run", Properties::MenuFont(), sf::Color::Black, 30);
52  runItem->getSignal(Item::Activated).willAlwaysCall(std::bind(&PlayerMenu::runChosen, this));
53 
54  actionMenu.setRootItem(fightItem);
55  actionMenu.addItem(bagItem, fightItem.get(), Item::Right);
56  actionMenu.addItem(switchItem, fightItem.get(), Item::Bottom);
57  if (canRun) {
58  actionMenu.addItem(runItem, bagItem.get(), Item::Bottom);
59  actionMenu.attachExisting(runItem.get(), switchItem.get(), Item::Right);
60  }
61  else {
62  actionMenu.attachExisting(switchItem.get(), bagItem.get(), Item::Bottom, false);
63  actionMenu.attachExisting(bagItem.get(), switchItem.get(), Item::Right, false);
64  }
65  actionMenu.setPosition({513.f, 476.f});
66  actionMenu.setPadding({40.f, 17.f});
67 
68  moveMenu.setPosition({16.f, 477.f});
69  moveMenu.setPadding({25.f, 20.f});
70 
71  moveTxtr = engine.renderer().texturePool().getOrLoadTexture(
72  bl::util::FileUtil::joinPath(Properties::ImagePath(), "Battle/movebox.png"));
73  moveBox.create(engine, moveTxtr);
74  moveBox.getTransform().setPosition(MoveBoxPos);
75  moveBox.addToScene(scene, bl::rc::UpdateSpeed::Static);
76 
77  movePwr.create(engine, Properties::MenuFont(), "", 25, sf::Color::Black);
78  movePwr.getTransform().setPosition(77.f, 20.f);
79  movePwr.setParent(moveBox);
80  movePwr.addToScene(scene, bl::rc::UpdateSpeed::Static);
81 
82  moveAcc.create(engine, Properties::MenuFont(), "", 25, sf::Color::Black);
83  moveAcc.getTransform().setPosition(77.f, 53.f);
84  moveAcc.setParent(moveBox);
85  moveAcc.addToScene(scene, bl::rc::UpdateSpeed::Static);
86 
87  movePP.create(engine, Properties::MenuFont(), "", 25, sf::Color::Black);
88  movePP.getTransform().setPosition(77.f, 87.f);
89  movePP.setParent(moveBox);
90  movePP.addToScene(scene, bl::rc::UpdateSpeed::Static);
91 }
92 
94  using namespace bl::menu;
95 
96  currentPeoplemon = i;
97  moves = ppl.base().knownMoves();
98  for (int i = 0; i < 4; ++i) { moveItems[i].reset(); }
99 
100  for (int i = 0; i < 4; ++i) {
101  if (moves[i].id == pplmn::MoveId::Unknown) break;
102 
103  moveItems[i] = TextItem::create(
104  pplmn::Move::name(moves[i].id), Properties::MenuFont(), sf::Color::Black, 24);
105  moveItems[i]
106  ->getSignal(Item::Activated)
107  .willAlwaysCall(std::bind(&PlayerMenu::moveChosen, this, i));
108  moveItems[i]
109  ->getSignal(Item::Selected)
110  .willAlwaysCall(std::bind(&PlayerMenu::syncMove, this, i));
111  if (i == 1) { moveItems[i]->overridePosition({240.f, 0.f}); }
112  }
113 
114  moveMenu.setRootItem(moveItems[0]);
115  if (moveItems[1]) {
116  moveMenu.addItem(moveItems[1], moveItems[0].get(), Item::Right);
117  if (moveItems[2]) {
118  moveMenu.addItem(moveItems[2], moveItems[0].get(), Item::Bottom);
119  if (moveItems[3]) {
120  moveMenu.addItem(moveItems[3], moveItems[1].get(), Item::Bottom);
121  moveMenu.attachExisting(moveItems[3].get(), moveItems[2].get(), Item::Right);
122  }
123  else {
124  moveMenu.attachExisting(
125  moveItems[2].get(), moveItems[1].get(), Item::Bottom, false);
126  moveMenu.attachExisting(moveItems[1].get(), moveItems[2].get(), Item::Right, false);
127  }
128  }
129  }
130 }
131 
133  switch (state) {
134  case State::PickingItem:
135  if (chosenItem != item::Id::None) { state = State::Hidden; }
136  else if (stateLoopGuard) { stateLoopGuard = false; }
137  else { state = State::PickingAction; }
138  break;
139  case State::PickingPeoplemon:
140  if (chosenMoveOrPeoplemon != -1 && chosenMoveOrPeoplemon != currentPeoplemon) {
141  state = State::Hidden;
142  }
143  else if (stateLoopGuard) { stateLoopGuard = false; }
144  else {
145  state = State::PickingAction;
146  chosenMoveOrPeoplemon = -1;
147  }
148  break;
149  default:
150  break;
151  }
152 }
153 
155  state = State::PickingAction;
156  menuDriver.drive(&actionMenu);
157 }
158 
159 void PlayerMenu::choosePeoplemonMidTurn(bool fromFaint, bool fromRevive) {
160  state = State::PickingPeoplemon;
161  chosenMoveOrPeoplemon = -1;
162  stateLoopGuard = true;
163  if (fromFaint) {
164  bl::event::Dispatcher::dispatch<event::OpenPeoplemonMenu>(
166  currentPeoplemon,
167  &chosenMoveOrPeoplemon});
168  }
169  else if (fromRevive) {
170  bl::event::Dispatcher::dispatch<event::OpenPeoplemonMenu>(
172  currentPeoplemon,
173  &chosenMoveOrPeoplemon});
174  }
175  else {
176  bl::event::Dispatcher::dispatch<event::OpenPeoplemonMenu>(
178  currentPeoplemon,
179  &chosenMoveOrPeoplemon});
180  }
181 }
182 
184  state = State::ChoosingMoveToForget;
185  menuDriver.drive(&moveMenu);
186 }
187 
188 bool PlayerMenu::ready() const { return state == State::Hidden; }
189 
190 TurnAction PlayerMenu::selectedAction() const { return chosenAction; }
191 
192 int PlayerMenu::selectedMove() const { return chosenMoveOrPeoplemon; }
193 
194 item::Id PlayerMenu::selectedItem() const { return chosenItem; }
195 
196 int PlayerMenu::selectedPeoplemon() const { return chosenMoveOrPeoplemon; }
197 
199  menuDriver.sendControl(cmd, fromEvent);
200  if (cmd == input::Control::Back && fromEvent) {
201  if (state == State::PickingMove) {
202  state = State::PickingAction;
203  menuDriver.drive(&actionMenu);
204  bl::audio::AudioSystem::playOrRestartSound(Properties::MenuBackSound());
205  }
206  else if (state == State::ChoosingMoveToForget) {
207  // TODO - maybe confirm here that player wants to not learn
208  moveChosen(-1);
209  }
210  }
211 }
212 
213 void PlayerMenu::render(bl::rc::scene::CodeScene::RenderContext& ctx) {
214  if (state == State::PickingAction) { actionMenu.draw(ctx); }
215  else if (state == State::PickingMove || state == State::ChoosingMoveToForget) {
216  moveMenu.draw(ctx);
217  moveBox.draw(ctx);
218  movePP.draw(ctx);
219  movePwr.draw(ctx);
220  moveAcc.draw(ctx);
221  }
222 }
223 
224 void PlayerMenu::fightChosen() {
225  state = State::PickingMove;
226  chosenAction = TurnAction::Fight;
227 
228  bool useFlail = true;
229  for (int i = 0; i < 4; ++i) {
230  if (moves[i].id != pplmn::MoveId::Unknown && moves[i].curPP > 0) {
231  useFlail = false;
232  break;
233  }
234  }
235  if (useFlail) {
236  state = State::Hidden;
237  chosenMoveOrPeoplemon = -1;
238  }
239  else {
240  menuDriver.drive(&moveMenu);
241  for (int i = 0; i < 4; ++i) {
242  if (moveMenu.getSelectedItem() == moveItems[i].get()) {
243  syncMove(i);
244  break;
245  }
246  }
247  }
248 }
249 
250 void PlayerMenu::switchChosen() {
251  state = State::PickingPeoplemon;
252  chosenAction = TurnAction::Switch;
253  chosenMoveOrPeoplemon = -1;
254  stateLoopGuard = true;
255  bl::event::Dispatcher::dispatch<event::OpenPeoplemonMenu>(
257  currentPeoplemon,
258  &chosenMoveOrPeoplemon});
259 }
260 
261 void PlayerMenu::itemChosen() {
262  state = State::PickingItem;
263  chosenAction = TurnAction::Item;
264  stateLoopGuard = true;
265  chosenItem = item::Id::None;
266  bl::event::Dispatcher::dispatch<event::OpenBagMenu>({event::OpenBagMenu::Context::BattleUse,
267  &chosenItem,
268  currentPeoplemon,
269  &chosenMoveOrPeoplemon});
270 }
271 
272 void PlayerMenu::runChosen() {
273  chosenAction = TurnAction::Run;
274  state = State::Hidden;
275 }
276 
277 void PlayerMenu::moveChosen(int i) {
278  chosenMoveOrPeoplemon = i;
279  state = State::Hidden;
280 }
281 
282 void PlayerMenu::syncMove(int i) {
283  movePP.getSection().setString(std::to_string(moves[i].curPP) + "/" +
284  std::to_string(moves[i].maxPP));
285  movePwr.getSection().setString(std::to_string(pplmn::Move::damage(moves[i].id)));
286  moveAcc.getSection().setString(std::to_string(pplmn::Move::accuracy(moves[i].id)));
287 }
288 
289 } // namespace view
290 } // namespace battle
291 } // namespace core
Id
Represents an item in its simplist form.
Definition: Id.hpp:24
Core classes and functionality for both the editor and game.
TurnAction
Represents an action that a battler may take on their turn.
Definition: TurnAction.hpp:16
std::underlying_type_t< Control::EntityControl > EntityControl
Helper typedef to avoid too much casting boilerplate.
Definition: Control.hpp:44
void handleInput(input::EntityControl input, bool ignoreDebounce)
Processes player input to update the menu state.
Definition: PlayerMenu.cpp:198
TurnAction selectedAction() const
The selected turn action.
Definition: PlayerMenu.cpp:190
void chooseMoveToForget()
Initiates the process of choosing the move to forget.
Definition: PlayerMenu.cpp:183
int selectedPeoplemon() const
Returns the selected peoplemon index.
Definition: PlayerMenu.cpp:196
PlayerMenu(bl::engine::Engine &engine, bool canRun)
Construct a new Player Menu.
Definition: PlayerMenu.cpp:21
void setPeoplemon(int i, const pplmn::BattlePeoplemon &ppl)
Updates the menu for the given peoplemon.
Definition: PlayerMenu.cpp:93
void render(bl::rc::scene::CodeScene::RenderContext &ctx)
Renders the menu.
Definition: PlayerMenu.cpp:213
void choosePeoplemonMidTurn(bool fromFaint, bool fromRevive)
Opens the menu to select a peoplemon to send out.
Definition: PlayerMenu.cpp:159
item::Id selectedItem() const
Returns the selected item.
Definition: PlayerMenu.cpp:194
void beginTurn()
Resets the menu to the turn start state.
Definition: PlayerMenu.cpp:154
int selectedMove() const
Returns the selected move index.
Definition: PlayerMenu.cpp:192
void init(bl::rc::scene::CodeScene *scene)
Creates UI elements and adds them to the scene.
Definition: PlayerMenu.cpp:31
void refresh()
Polls state from opened peoplemon or bag menu.
Definition: PlayerMenu.cpp:132
bool ready() const
Returns true when the player's choice has been made.
Definition: PlayerMenu.cpp:188
Represents a Peoplemon in battle. Stores some extra state that only exists in battle....
OwnedPeoplemon & base()
Returns the wrapped peoplemon.
static int damage(MoveId move)
Returns the damage of the given move.
Definition: Move.cpp:86
static int accuracy(MoveId move)
Returns the accuracy of the given move.
Definition: Move.cpp:91
static const std::string & name(MoveId move)
Returns the name of the given move.
Definition: Move.cpp:71
const OwnedMove * knownMoves() const
Returns the moves known by this Peoplemon.
static const sf::VulkanFont & MenuFont()
Definition: Properties.cpp:363
static bl::audio::AudioSystem::Handle MenuBackSound()
Definition: Properties.cpp:712
static const std::string & ImagePath()
Definition: Properties.cpp:333