1 ////////////////////////////////////////////////////////////////////////////////
2 // Copyright (C) 2004-2011 by The Allacrost Project
3 // Copyright (C) 2012-2018 by Bertram (Valyria Tear)
4 // All Rights Reserved
5 //
6 // This code is licensed under the GNU GPL version 2. It is free software and
7 // you may modify it and/or redistribute it under the terms of this license.
8 // See https://www.gnu.org/copyleft/gpl.html for details.
9 ////////////////////////////////////////////////////////////////////////////////
10
11 #include "modes/battle/finish/battle_victory.h"
12
13 #include "modes/battle/battle.h"
14 #include "modes/battle/objects/battle_character.h"
15 #include "modes/battle/objects/battle_enemy.h"
16
17 #include "modes/menu/menu_mode.h"
18
19 #include "common/global/global.h"
20 #include "common/global/actors/global_character.h"
21
22 #include "common/gui/menu_window.h"
23
24 #include "engine/video/video_utils.h"
25 #include "engine/system.h"
26 #include "engine/input.h"
27 #include "engine/audio/audio.h"
28
29 #include <assert.h>
30
31 using namespace vt_gui;
32 using namespace vt_video;
33 using namespace vt_system;
34 using namespace vt_global;
35 using namespace vt_input;
36 using namespace vt_utils;
37 using namespace vt_audio;
38
39 namespace vt_battle
40 {
41
42 namespace private_battle
43 {
44
45 //! \brief Draw position and dimension constants used for GUI objects
46 //@{
47 const float TOP_WINDOW_XPOS = 240.0f;
48 const float TOP_WINDOW_YPOS = 104.0f;
49 const float TOP_WINDOW_WIDTH = 600.0f;
50 const float TOP_WINDOW_HEIGHT = 64.0f;
51
52 const float CHAR_WINDOW_XPOS = 360.0f;
53 const float CHAR_WINDOW_YPOS = 104.0f+ TOP_WINDOW_HEIGHT - 1.0f;
54 const float CHAR_WINDOW_WIDTH = 380.0f;
55 const float CHAR_WINDOW_HEIGHT = 118.0f;
56
57 const float SPOILS_WINDOW_XPOS = 550.0f;
58 const float SPOILS_WINDOW_YPOS = 104.0f + TOP_WINDOW_HEIGHT - 1.0f;
59 const float SPOILS_WINDOW_WIDTH = 360.0f;
60 const float SPOILS_WINDOW_HEIGHT = 320.0f;
61 //@}
62
63 //! \brief The set of victory options that the player can select
64 //@{
65 //! End battle
66 const uint32_t VICTORY_OPTION_END_BATTLE = 0;
67 //! Improve skills
68 const uint32_t VICTORY_OPTION_IMPROVE_SKILLS = 1;
69 //@}
70
BattleVictory()71 BattleVictory::BattleVictory() :
72 _state(VICTORY_INVALID),
73 _characters_number(0),
74 _xp_earned(0),
75 _drunes_dropped(0),
76 _begin_counting_xp(false),
77 _begin_counting_drunes(false),
78 _number_character_windows_created(0)
79 {
80 _outcome_text.SetPosition(212.0f, 30.0f);
81 _outcome_text.SetDimensions(512.0f, 50.0f);
82 _outcome_text.SetTextStyle(TextStyle("text28", Color::white));
83 _outcome_text.SetDisplayMode(VIDEO_TEXT_INSTANT);
84 _outcome_text.SetDisplayText(UTranslate("The heroes were victorious!"));
85
86 _header_window.Create(TOP_WINDOW_WIDTH, TOP_WINDOW_HEIGHT, ~VIDEO_MENU_EDGE_BOTTOM, VIDEO_MENU_EDGE_BOTTOM);
87 _header_window.SetPosition(TOP_WINDOW_XPOS, TOP_WINDOW_YPOS);
88 _header_window.SetAlignment(VIDEO_X_LEFT, VIDEO_Y_TOP);
89 _header_window.Show();
90
91 _spoils_window.Create(SPOILS_WINDOW_WIDTH, SPOILS_WINDOW_HEIGHT);
92 _spoils_window.SetPosition(SPOILS_WINDOW_XPOS, SPOILS_WINDOW_YPOS);
93 _spoils_window.SetAlignment(VIDEO_X_LEFT, VIDEO_Y_TOP);
94 _spoils_window.Show();
95
96 _header_xp.SetOwner(&_header_window);
97 _header_xp.SetPosition(30.0f, 30.0f);
98 _header_xp.SetDimensions(TOP_WINDOW_WIDTH / 5.0f * 4.0f, 40.0f);
99 _header_xp.SetAlignment(VIDEO_X_LEFT, VIDEO_Y_CENTER);
100 _header_xp.SetTextStyle(TextStyle("text20", Color::white));
101 _header_xp.SetDisplayMode(VIDEO_TEXT_INSTANT);
102
103 // Reset raw XP bonus
104 for(uint32_t i = 0; i < 4; i++) {
105 _raw_xp_given[i] = true;
106 _raw_xp_won[i] = false;
107 }
108
109 _drunes_dropped_text.SetOwner(&_header_window);
110 _drunes_dropped_text.SetPosition(300.0f, 30.0f);
111 _drunes_dropped_text.SetDimensions(TOP_WINDOW_WIDTH / 5.0f * 2.0f, 40.0f);
112 _drunes_dropped_text.SetAlignment(VIDEO_X_LEFT, VIDEO_Y_CENTER);
113 _drunes_dropped_text.SetTextStyle(TextStyle("text20", Color::white));
114 _drunes_dropped_text.SetDisplayMode(VIDEO_TEXT_INSTANT);
115
116 _total_drunes.SetOwner(&_spoils_window);
117 _total_drunes.SetPosition(SPOILS_WINDOW_WIDTH / 4.0f, 0.0f);
118 _total_drunes.SetDimensions(SPOILS_WINDOW_WIDTH / 4.0f * 3.0f, 40.0f);
119 _total_drunes.SetTextStyle(TextStyle("text20", Color::white));
120 _total_drunes.SetDisplayMode(VIDEO_TEXT_INSTANT);
121
122 _object_header_text.SetOwner(&_spoils_window);
123 _object_header_text.SetPosition(SPOILS_WINDOW_WIDTH / 4.0f, 50.0f);
124 _object_header_text.SetDimensions(SPOILS_WINDOW_WIDTH / 4.0f * 3.0f, 40.0f);
125 _object_header_text.SetTextStyle(TextStyle("title20", Color::white));
126 _object_header_text.SetDisplayMode(VIDEO_TEXT_INSTANT);
127 _object_header_text.SetDisplayText(UTranslate("Items Found"));
128
129 _object_list.SetOwner(&_spoils_window);
130 _object_list.SetPosition(50.0f, 100.0f);
131 _object_list.SetDimensions(250.0f, 180.0f, 1, 8, 1, 8);
132 _object_list.SetTextStyle(TextStyle("text20", Color::white));
133 _object_list.SetAlignment(VIDEO_X_LEFT, VIDEO_Y_TOP);
134 _object_list.SetOptionAlignment(VIDEO_X_LEFT, VIDEO_Y_CENTER);
135 _object_list.SetCursorState(VIDEO_CURSOR_STATE_HIDDEN);
136
137 _victory_options.SetOwner(&_header_window);
138 _victory_options.SetPosition(TOP_WINDOW_WIDTH / 2, 30.0f);
139 _victory_options.SetDimensions(TOP_WINDOW_WIDTH, 50.0f, 2, 1, 2, 1);
140 _victory_options.SetTextStyle(TextStyle("text22", Color::white, VIDEO_TEXT_SHADOW_DARK));
141 _victory_options.SetAlignment(VIDEO_X_CENTER, VIDEO_Y_CENTER);
142 _victory_options.SetOptionAlignment(VIDEO_X_CENTER, VIDEO_Y_CENTER);
143 _victory_options.SetSelectMode(VIDEO_SELECT_SINGLE);
144 _victory_options.SetHorizontalWrapMode(VIDEO_WRAP_MODE_STRAIGHT);
145 _victory_options.SetCursorOffset(-60.0f, -25.0f);
146 _victory_options.AddOption(UTranslate("End Battle"));
147 _victory_options.AddOption(UTranslate("Improve Skills"));
148 _victory_options.SetSelection(0);
149 }
150
~BattleVictory()151 BattleVictory::~BattleVictory()
152 {
153 _header_window.Destroy();
154 _spoils_window.Destroy();
155
156 for (uint32_t i = 0; i < _number_character_windows_created; ++i) {
157 _character_window[i].Destroy();
158 }
159
160 // Add all the objects that were dropped by enemies to the party's inventory.
161 for (auto i = _objects_dropped.begin(); i != _objects_dropped.end(); ++i) {
162
163 // Add the item to the inventory.
164 assert(i->first != nullptr);
165 GlobalManager->GetInventoryHandler().AddToInventory(i->first->GetID(), i->second);
166 }
167 _objects_dropped.clear();
168
169 // Update the HP and SP of all characters.
170 _SetCharacterStatus();
171 }
172
Initialize()173 void BattleVictory::Initialize()
174 {
175 // Prepare all character data
176 std::deque<BattleCharacter *>& all_characters = BattleMode::CurrentInstance()->GetCharacterActors();
177 // Reinit the number of living characters
178 uint32_t alive_characters_number = 0;
179
180 _characters_number = all_characters.size();
181
182 for(uint32_t i = 0; i < _characters_number; ++i) {
183 _characters.push_back(all_characters[i]->GetGlobalCharacter());
184 _character_portraits[i] = all_characters[i]->GetPortrait();
185
186 // Only size up non valid images
187 if(!_character_portraits[i].GetFilename().empty())
188 _character_portraits[i].SetDimensions(100.0f, 100.0f);
189
190 if(all_characters[i]->IsAlive()) {
191 // Set up the victory animation for the living beings
192 all_characters[i]->ChangeSpriteAnimation("victory");
193 // Adds a living player to later split xp with.
194 ++alive_characters_number;
195 } else {
196 // Gray out portraits of deceased characters
197 _character_portraits[i].SetGrayscale(true);
198 }
199 }
200
201 // Collect the XP, drunes, and dropped objects for each defeated enemy
202 std::deque<BattleEnemy*>& all_enemies = BattleMode::CurrentInstance()->GetEnemyActors();
203 for (uint32_t i = 0; i < all_enemies.size(); ++i) {
204 GlobalEnemy* enemy = all_enemies[i]->GetGlobalEnemy();
205 assert(enemy != nullptr);
206
207 _xp_earned += enemy->GetExperiencePoints();
208 _drunes_dropped += enemy->GetDrunesDropped();
209
210 std::vector<std::shared_ptr<GlobalObject>> objects = enemy->DetermineDroppedObjects();
211 for (uint32_t j = 0; j < objects.size(); ++j) {
212 // Check if the object to add is already in our list. If so, just increase the quantity of that object.
213 // iter = _objects_dropped.find(objects[j]); // Will not work since each item is created with new.
214 // Need to search for the item ID instead.
215 auto iter = _objects_dropped.begin();
216 while (iter != _objects_dropped.end()) {
217 if (iter->first->GetID() == objects[j]->GetID()) {
218 break;
219 }
220 ++iter;
221 }
222
223 if (iter != _objects_dropped.end()) {
224 ++iter->second;
225 } else {
226 _objects_dropped.insert(std::make_pair(objects[j], 1));
227 }
228 }
229 objects.clear();
230 }
231
232 // Divide up the XP earnings by the number of players (only living ones)
233 if (alive_characters_number > 0)
234 _xp_earned /= alive_characters_number;
235 else
236 _xp_earned /= 4; // Should never happen.
237
238 // Compute the raw fighting XP bonus for each characters (20% of character's XP)
239 for(uint32_t i = 0; i < _characters.size() && i < 4; ++i) {
240 if (_characters[i]->HasEquipment()) {
241 _raw_xp_won[i] = false;
242 _raw_xp_given[i] = true;
243 }
244 else {
245 _raw_xp_won[i] = true;
246 _raw_xp_given[i] = false;
247 }
248 }
249
250 _CreateCharacterGUIObjects();
251 _CreateObjectList();
252
253 // Initialize dynamic texts
254 _header_xp.SetDisplayText(UTranslate("XP Earned: ") + MakeUnicodeString(NumberToString(_xp_earned)));
255 _drunes_dropped_text.SetDisplayText(UTranslate("Drunes Found: ") + MakeUnicodeString(NumberToString(_drunes_dropped)));
256 _total_drunes.SetDisplayText(UTranslate("Total Drunes: ") + MakeUnicodeString(NumberToString(GlobalManager->GetDrunes())));
257
258 // Start victory
259 _state = VICTORY_START;
260 }
261
Update()262 void BattleVictory::Update()
263 {
264 switch(_state) {
265 case VICTORY_START:
266 // Go to exit menu once count is done
267 if (_xp_earned == 0 && _drunes_dropped == 0) {
268 _state = VICTORY_END;
269 }
270
271 _UpdateXP();
272 _UpdateSpoils();
273 break;
274
275 case VICTORY_END:
276 _UpdateEndMenu();
277 break;
278
279 default:
280 IF_PRINT_WARNING(BATTLE_DEBUG) << "invalid finish state: " << _state << std::endl;
281 break;
282 }
283 }
284
Draw()285 void BattleVictory::Draw()
286 {
287 _outcome_text.Draw();
288
289 // Header Windows
290 _header_window.Draw();
291
292 if (_state == VICTORY_END) {
293 _victory_options.Draw();
294 }
295 else {
296 _header_xp.Draw();
297 _drunes_dropped_text.Draw();
298 }
299
300 for(uint32_t i = 0; i < _characters_number; ++i) {
301 _character_window[i].Draw();
302 _DrawXP(i);
303 }
304
305 // Items and drunes
306 _spoils_window.Draw();
307 _total_drunes.Draw();
308 _object_header_text.Draw();
309 _object_list.Draw();
310 }
311
_CreateCharacterGUIObjects()312 void BattleVictory::_CreateCharacterGUIObjects()
313 {
314 // Create the character windows. The lowest one does not have its lower border removed
315 float next_ypos = CHAR_WINDOW_YPOS;
316 for(uint32_t i = 0; i < _characters_number; ++i) {
317 _number_character_windows_created++;
318 if((i + 1) >= _characters_number) {
319 _character_window[i].Create(CHAR_WINDOW_WIDTH, CHAR_WINDOW_HEIGHT);
320 } else {
321 _character_window[i].Create(CHAR_WINDOW_WIDTH, CHAR_WINDOW_HEIGHT, ~VIDEO_MENU_EDGE_BOTTOM, VIDEO_MENU_EDGE_BOTTOM);
322 }
323
324 _character_window[i].SetPosition(CHAR_WINDOW_XPOS, next_ypos);
325 _character_window[i].SetAlignment(VIDEO_X_CENTER, VIDEO_Y_TOP);
326 _character_window[i].Show();
327 next_ypos += CHAR_WINDOW_HEIGHT;
328 }
329
330 // Construct GUI objects that will fill each character window
331 for(uint32_t i = 0; i < _characters_number; ++i) {
332 _level_text[i].SetOwner(&_character_window[i]);
333 _level_text[i].SetPosition(130.0f, 20.0f);
334 _level_text[i].SetDimensions(300.0f, 25.0f);
335 _level_text[i].SetTextStyle(TextStyle("text20", Color::white));
336 _level_text[i].SetDisplayMode(VIDEO_TEXT_INSTANT);
337
338 _xp_text[i].SetOwner(&_character_window[i]);
339 _xp_text[i].SetPosition(130.0f, 50.0f);
340 _xp_text[i].SetDimensions(300.0f, 25.0f);
341 _xp_text[i].SetTextStyle(TextStyle("text20", Color::white));
342 _xp_text[i].SetDisplayMode(VIDEO_TEXT_INSTANT);
343
344 _unspent_xp[i].SetOwner(&_character_window[i]);
345 _unspent_xp[i].SetPosition(130.0f, 80.0f);
346 _unspent_xp[i].SetDimensions(300.0f, 25.0f);
347 _unspent_xp[i].SetTextStyle(TextStyle("text20", Color::white));
348 _unspent_xp[i].SetDisplayMode(VIDEO_TEXT_INSTANT);
349
350 // Don't show XP when the maximum level has been reached.
351 if(_characters[i]->GetExperienceLevel() >= GlobalManager->GetMaxExperienceLevel()) {
352 _level_text[i].SetDisplayText(UTranslate("Level (Max): ")
353 + MakeUnicodeString(NumberToString(_characters[i]->GetExperienceLevel())));
354 _xp_text[i].SetDisplayText(" ");
355 } else {
356 _level_text[i].SetDisplayText(UTranslate("Level: ")
357 + MakeUnicodeString(NumberToString(_characters[i]->GetExperienceLevel())));
358 _xp_text[i].SetDisplayText(UTranslate("XP for level up: ")
359 + MakeUnicodeString(NumberToString(_characters[i]->GetExperienceForNextLevel())));
360 _unspent_xp[i].SetDisplayText(UTranslate("XP for skills: ")
361 + MakeUnicodeString(NumberToString(_characters[i]->GetUnspentExperiencePoints())));
362 }
363 }
364 }
365
_CreateObjectList()366 void BattleVictory::_CreateObjectList()
367 {
368 // Add all dropped items in the list
369 for (auto i = _objects_dropped.begin(); i != _objects_dropped.end(); ++i) {
370 std::shared_ptr<GlobalObject> obj = i->first;
371 if (obj->GetIconImage().GetFilename().empty()) {
372 _object_list.AddOption(MakeUnicodeString("<30>") +
373 obj->GetName() + MakeUnicodeString("<R>x" + NumberToString(i->second)));
374 }
375 else {
376 _object_list.AddOption(MakeUnicodeString("<" + obj->GetIconImage().GetFilename() + "><30>") +
377 obj->GetName() + MakeUnicodeString("<R>x" + NumberToString(i->second)));
378 }
379 }
380
381 // Resize all icon images so that they are the same height as the text
382 for(uint32_t i = 0; i < _object_list.GetNumberOptions(); ++i) {
383 StillImage* image = _object_list.GetEmbeddedImage(i);
384 if (image != nullptr)
385 _object_list.GetEmbeddedImage(i)->SetDimensions(30.0f, 30.0f);
386 }
387
388 // Set item found title accordingly
389 const uint32_t no_of_options = _object_list.GetNumberOptions();
390 _object_header_text.SetDisplayText(no_of_options == 0 ?
391 // tr: Header in battle result screen: 0 items found
392 UTranslate("No Items Found") :
393 no_of_options == 1 ?
394 // tr: Header in battle result screen: 1 item found
395 UTranslate("Item Found") :
396 // tr: Header in battle result screen: more than 1 item found
397 UTranslate("Items Found"));
398 }
399
_SetCharacterStatus()400 void BattleVictory::_SetCharacterStatus()
401 {
402 std::deque<BattleCharacter *>& battle_characters = BattleMode::CurrentInstance()->GetCharacterActors();
403
404 for(std::deque<BattleCharacter *>::iterator i = battle_characters.begin(); i != battle_characters.end(); ++i) {
405 GlobalCharacter *character = (*i)->GetGlobalCharacter();
406
407 // Put back the current HP / SP onto the global characters.
408 character->SetHitPoints((*i)->GetHitPoints());
409 character->SetSkillPoints((*i)->GetSkillPoints());
410 }
411 }
412
_UpdateXP()413 void BattleVictory::_UpdateXP()
414 {
415 // The number of milliseconds that we wait in between updating the XP count
416 const uint32_t UPDATE_PERIOD = 50;
417 // A simple counter used to keep track of when the next XP count should begin
418 static uint32_t time_counter = 0;
419
420 // The amount of XP to add to each character this update cycle
421 uint32_t xp_to_add = 0;
422
423 // Process confirm press inputs.
424 if(InputManager->ConfirmPress()) {
425 // Begin counting out XP earned
426 if(!_begin_counting_xp) {
427 _begin_counting_xp = true;
428 }
429 // If confirm received during counting, instantly add all remaining XP
430 else if(_xp_earned != 0) {
431 xp_to_add = _xp_earned;
432 }
433 }
434
435 // If counting has not began or counting is alreasy finished, there is nothing more to do here
436 if(!_begin_counting_xp || (_xp_earned == 0))
437 return;
438
439 // Update the timer and determine how much XP to add if the time has been reached
440 // We don't want to modify the XP to add if a confirm event occurred in step (1)
441 if(xp_to_add == 0) {
442 time_counter += SystemManager->GetUpdateTime();
443 if(time_counter >= UPDATE_PERIOD) {
444 time_counter -= UPDATE_PERIOD;
445
446 // Determine an appropriate amount of XP to add here
447 if(_xp_earned > 10000)
448 xp_to_add = 1000;
449 else if(_xp_earned > 1000)
450 xp_to_add = 100;
451 else if(_xp_earned > 100)
452 xp_to_add = 10;
453 else
454 xp_to_add = 1;
455 }
456 }
457
458 // If there is no XP to add this update cycle, there is nothing left for us to do
459 if(xp_to_add == 0)
460 return;
461
462 // Add the XP amount to the characters appropriately
463 std::deque<BattleCharacter *>& battle_characters = BattleMode::CurrentInstance()->GetCharacterActors();
464 for(uint32_t i = 0; i < _characters_number; ++i) {
465 // Don't add experience points to dead characters
466 if(!battle_characters[i]->IsAlive())
467 continue;
468
469 // Tells whether the character can receive XP
470 bool level_maxed_out = false;
471
472 // Don't permit to earn XP when the maximum level has been reached.
473 if(battle_characters[i]->GetGlobalCharacter()->GetExperienceLevel() >= GlobalManager->GetMaxExperienceLevel())
474 level_maxed_out = true;
475
476 uint32_t xp_added = xp_to_add;
477 // Add the raw bonus when not given yet (+20% XP)
478 if (_raw_xp_given[i] == false) {
479 if (_xp_earned > 100) {
480 xp_added += (xp_to_add / 5);
481 }
482 else {
483 // When giving one xp point at a time,
484 // we give all the rest of the raw bonus and set it as done.
485 xp_added += _xp_earned / 5;
486 _raw_xp_given[i] = true;
487 }
488
489 }
490
491 if(!level_maxed_out && _characters[i]->AddExperiencePoints(xp_added)) {
492 AudioManager->PlaySound("data/sounds/levelup.wav");
493 }
494
495 ustring level_text;
496 ustring xp_text;
497 ustring unspent_xp;
498 if(level_maxed_out) {
499 level_text = UTranslate("Level (Max): ") + MakeUnicodeString(NumberToString(_characters[i]->GetExperienceLevel()));
500 } else {
501 level_text = UTranslate("Level: ") + MakeUnicodeString(NumberToString(_characters[i]->GetExperienceLevel()));
502 xp_text = UTranslate("XP for level up: ") + MakeUnicodeString(NumberToString(_characters[i]->GetExperienceForNextLevel()));
503 if (_raw_xp_won[i])
504 xp_text += UTranslate(" (+20%)");
505 unspent_xp = UTranslate("XP for skills: ")
506 + MakeUnicodeString(NumberToString(_characters[i]->GetUnspentExperiencePoints()));
507 }
508
509 _level_text[i].SetDisplayText(level_text);
510 _xp_text[i].SetDisplayText(xp_text);
511 _unspent_xp[i].SetDisplayText(unspent_xp);
512 }
513
514 _xp_earned -= xp_to_add;
515 _header_xp.SetDisplayText(UTranslate("XP Earned: ") + MakeUnicodeString(NumberToString(_xp_earned)));
516 }
517
_UpdateSpoils()518 void BattleVictory::_UpdateSpoils()
519 {
520 // The number of milliseconds that we wait in between updating the drunes count
521 const uint32_t UPDATE_PERIOD = 50;
522 // A simple counter used to keep track of when the next drunes count should begin
523 static uint32_t time_counter = 0;
524 // TODO: Add drunes gradually instead of all at once
525 static uint32_t drunes_to_add = 0;
526
527 // Process confirm press inputs.
528 if(InputManager->ConfirmPress()) {
529 // Begin counting out drunes dropped
530 if(!_begin_counting_drunes)
531 _begin_counting_drunes = true;
532
533 // If confirm received during counting, instantly add all remaining drunes
534 else if(_drunes_dropped != 0) {
535 drunes_to_add = _drunes_dropped;
536 }
537 }
538
539 // If counting has not began or counting is alreasy finished, there is nothing more to do here
540 if(!_begin_counting_drunes || (_drunes_dropped == 0))
541 return;
542
543 // Update the timer and determine how many drunes to add if the time has been reached
544 // We don't want to modify the drunes to add if a confirm event occurred in step (1)
545 if(drunes_to_add == 0) {
546 time_counter += SystemManager->GetUpdateTime();
547 if(time_counter >= UPDATE_PERIOD) {
548 time_counter -= UPDATE_PERIOD;
549
550 // Determine an appropriate amount of drunes to add here
551 if(_drunes_dropped > 10000)
552 drunes_to_add = 1000;
553 else if(_drunes_dropped > 1000)
554 drunes_to_add = 100;
555 else if(_drunes_dropped > 100)
556 drunes_to_add = 10;
557 else
558 drunes_to_add = 1;
559 }
560 }
561
562 // Add drunes and update the display
563 if(drunes_to_add != 0) {
564 // Avoid making _drunes_dropped a negative value
565 if(drunes_to_add > _drunes_dropped) {
566 drunes_to_add = _drunes_dropped;
567 }
568
569 GlobalManager->AddDrunes(drunes_to_add);
570 _drunes_dropped -= drunes_to_add;
571 _drunes_dropped_text.SetDisplayText(UTranslate("Drunes Found: ") + MakeUnicodeString(NumberToString(_drunes_dropped)));
572 _total_drunes.SetDisplayText(UTranslate("Total Drunes: ") + MakeUnicodeString(NumberToString(GlobalManager->GetDrunes())));
573 }
574 }
575
_UpdateEndMenu()576 void BattleVictory::_UpdateEndMenu()
577 {
578 _victory_options.Update();
579
580 if (InputManager->LeftPress()) {
581 _victory_options.InputLeft();
582 }
583 else if (InputManager->RightPress()) {
584 _victory_options.InputRight();
585 }
586 else if (InputManager->ConfirmPress()) {
587 switch(_victory_options.GetSelection()) {
588 default:
589 case VICTORY_OPTION_END_BATTLE:
590 BattleMode::CurrentInstance()->ChangeState(BATTLE_STATE_EXITING);
591 break;
592 case VICTORY_OPTION_IMPROVE_SKILLS:
593 vt_menu::MenuMode* menu_mode = new vt_menu::MenuMode();
594 menu_mode->GoToImproveSkillMenu();
595 _victory_options.SetSelection(VICTORY_OPTION_END_BATTLE);
596 vt_mode_manager::ModeManager->Push(menu_mode);
597 break;
598 }
599 }
600 }
601
_DrawXP(uint32_t index)602 void BattleVictory::_DrawXP(uint32_t index)
603 {
604 VideoManager->SetDrawFlags(VIDEO_X_LEFT, VIDEO_Y_TOP, 0);
605 VideoManager->Move(CHAR_WINDOW_XPOS - (CHAR_WINDOW_WIDTH / 2) + 20.0f,
606 (CHAR_WINDOW_YPOS + 17.0f) + (CHAR_WINDOW_HEIGHT * index));
607 _character_portraits[index].Draw();
608
609 _level_text[index].Draw();
610 _xp_text[index].Draw();
611 _unspent_xp[index].Draw();
612 }
613
614 } // namespace private_battle
615
616 } // namespace vt_battle
617