00001
00002
00003
00004
00005
00006
00007
00009
00018 #include <iostream>
00019 #include <sstream>
00020
00021 #include "utils.h"
00022 #include "audio.h"
00023 #include "video.h"
00024 #include "input.h"
00025 #include "mode_manager.h"
00026 #include "system.h"
00027 #include "global.h"
00028 #include "script.h"
00029 #include "battle.h"
00030 #include "battle_actors.h"
00031 #include "boot.h"
00032
00033 using namespace std;
00034
00035 using namespace hoa_utils;
00036 using namespace hoa_audio;
00037 using namespace hoa_video;
00038 using namespace hoa_mode_manager;
00039 using namespace hoa_input;
00040 using namespace hoa_system;
00041 using namespace hoa_global;
00042 using namespace hoa_script;
00043
00044 using namespace hoa_battle::private_battle;
00045 using namespace hoa_boot;
00046
00047 namespace hoa_battle {
00048
00049 bool BATTLE_DEBUG = false;
00050
00051 namespace private_battle {
00052
00053 BattleMode * current_battle = NULL;
00054
00056
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 ScriptEvent::ScriptEvent(BattleActor* source, BattleActor* target, GlobalSkill* skill, GlobalAttackPoint* attack_point) :
00074 _source(source),
00075 _skill(skill),
00076 _item(NULL),
00077 _attack_point(attack_point),
00078 _target(target)
00079 {
00080 _warm_up_time.Initialize(skill->GetWarmupTime());
00081 _warm_up_time.Run();
00082 }
00083
00084
00085 ScriptEvent::ScriptEvent(BattleActor* source, BattleActor* target, GlobalItem* item, GlobalAttackPoint* attack_point, uint32 warm_up_time) :
00086 _source(source),
00087 _skill(NULL),
00088 _item(item),
00089 _attack_point(attack_point),
00090 _target(target)
00091
00092 {
00093 _warm_up_time.Initialize(warm_up_time);
00094 _warm_up_time.Run();
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 ScriptEvent::~ScriptEvent()
00112 {
00113 }
00114
00115
00116 void ScriptEvent::Update()
00117 {
00118
00119 if (_warm_up_time.IsRunning())
00120 {
00121 float offset = SystemManager->GetUpdateTime() * (107.f / _warm_up_time.GetDuration());
00122
00123 _source->SetTimePortraitLocation(_source->GetTimePortraitLocation() + offset);
00124 }
00125
00126 }
00127
00128 void ScriptEvent::RunScript() {
00129
00130 if (_item)
00131 {
00132 if (_item->GetTargetType() == GLOBAL_TARGET_PARTY)
00133 {
00134 if (_target->IsEnemy())
00135 {
00136 BattleEnemyActor* bea;
00137
00138 for (uint32 i = 0; i < current_battle->GetNumberOfEnemies(); ++i)
00139 {
00140 bea = current_battle->GetEnemyActorAt(i);
00141 if (bea->IsAlive())
00142 {
00143 bea->CalcEvade(_attack_point);
00144 bea->CalcMetaPhysicalDefense(_attack_point);
00145 bea->CalcPhysicalDefense(_attack_point);
00146 }
00147
00148 _item->BattleUse(bea, _source);
00149 }
00150
00151
00152
00153
00154
00155
00156
00157 }
00158 else
00159 {
00160 BattleCharacterActor* bca;
00161
00162 for (uint32 i = 0; i < current_battle->GetNumberOfCharacters(); ++i)
00163 {
00164 bca = current_battle->GetPlayerCharacterAt(i);
00165 if (bca->IsAlive())
00166 {
00167 bca->CalcEvade(_attack_point);
00168 bca->CalcMetaPhysicalDefense(_attack_point);
00169 bca->CalcPhysicalDefense(_attack_point);
00170 }
00171
00172 _item->BattleUse(bca, _source);
00173 }
00174
00175
00176
00177
00178
00179
00180
00181 }
00182 }
00183 else
00184 {
00185 _target->CalcEvade(_attack_point);
00186 _target->CalcMetaPhysicalDefense(_attack_point);
00187 _target->CalcPhysicalDefense(_attack_point);
00188
00189 _item->BattleUse(_target, _source);
00190
00191
00192
00193
00194
00195
00196
00197 }
00198
00199 if (_item->GetCount() == 0)
00200 {
00201 GlobalManager->RemoveFromInventory(_item->GetID());
00202 }
00203 }
00204
00205 else if (_skill)
00206 {
00207 _source->CalcMetaPhysicalAttack();
00208 _source->CalcPhysicalAttack();
00209
00210 if (_skill->GetTargetType() == GLOBAL_TARGET_PARTY)
00211 {
00212 if (_target->IsEnemy())
00213 {
00214 BattleEnemyActor* bea;
00215
00216 for (uint32 i = 0; i < current_battle->GetNumberOfEnemies(); ++i)
00217 {
00218 bea = current_battle->GetEnemyActorAt(i);
00219 if (bea->IsAlive())
00220 {
00221 bea->CalcEvade(_attack_point);
00222 bea->CalcMetaPhysicalDefense(_attack_point);
00223 bea->CalcPhysicalDefense(_attack_point);
00224 }
00225
00226 _skill->BattleExecute(bea, _source);
00227 }
00228 }
00229 else
00230 {
00231 BattleCharacterActor* bca;
00232
00233 for (uint32 i = 0; i < current_battle->GetNumberOfCharacters(); ++i)
00234 {
00235 bca = current_battle->GetPlayerCharacterAt(i);
00236 if (bca->IsAlive())
00237 {
00238 bca->CalcEvade(_attack_point);
00239 bca->CalcMetaPhysicalDefense(_attack_point);
00240 bca->CalcPhysicalDefense(_attack_point);
00241 }
00242
00243 _skill->BattleExecute(bca, _source);
00244 }
00245 }
00246 }
00247 else
00248 {
00249
00250
00251 if (_target->IsAlive())
00252 {
00253 _target->CalcEvade(_attack_point);
00254 _target->CalcMetaPhysicalDefense(_attack_point);
00255 _target->CalcPhysicalDefense(_attack_point);
00256 }
00257
00258 _skill->BattleExecute(_target, _source);
00259
00260
00261
00262
00263
00264 }
00265
00266 _source->SetSkillPoints(_source->GetSkillPoints() - _skill->GetSPRequired());
00267 }
00268
00269
00270 if (_source)
00271 {
00272 _source->TEMP_ResetAttackTimer();
00273
00274
00275
00276
00277 }
00278 }
00279
00280 }
00281
00282
00284
00286
00287 BattleMode::BattleMode() :
00288 _initialized(false),
00289 _performing_script(false),
00290 _active_se(NULL),
00291 _battle_over(false),
00292 _victorious_battle(false),
00293 _victory_xp(0),
00294 _victory_sp(0),
00295 _victory_money(0),
00296 _victory_level(false),
00297 _victory_skill(false),
00298 _cursor_state(CURSOR_IDLE),
00299 _selected_character(NULL),
00300 _selected_target(NULL),
00301 _selected_attack_point(0),
00302 _current_number_swaps(0),
00303 _swap_countdown_timer(300000),
00304 _min_agility(9999),
00305 _next_monster_location_index(0)
00306 {
00307 if (BATTLE_DEBUG)
00308 cout << "BATTLE: BattleMode constructor invoked" << endl;
00309
00310 mode_type = MODE_MANAGER_BATTLE_MODE;
00311
00312 std::vector <hoa_video::StillImage> attack_point_indicator;
00313 StillImage frame;
00314 frame.SetDimensions(16, 16);
00315 frame.SetFilename("img/icons/battle/ap_indicator_fr0.png");
00316 attack_point_indicator.push_back(frame);
00317 frame.SetFilename("img/icons/battle/ap_indicator_fr1.png");
00318 attack_point_indicator.push_back(frame);
00319 frame.SetFilename("img/icons/battle/ap_indicator_fr2.png");
00320 attack_point_indicator.push_back(frame);
00321 frame.SetFilename("img/icons/battle/ap_indicator_fr3.png");
00322 attack_point_indicator.push_back(frame);
00323
00324 for (uint32 i = 0; i < attack_point_indicator.size(); i++) {
00325 if (!VideoManager->LoadImage(attack_point_indicator[i]))
00326 cerr << "BATTLE ERROR: Failed to load attack point indicator." << endl;
00327 }
00328
00329 for (uint32 i = 0; i < attack_point_indicator.size(); i++) {
00330 _attack_point_indicator.AddFrame(attack_point_indicator[i], 10);
00331 }
00332
00333
00334 _universal_time_meter.SetDimensions(10, 512);
00335 _universal_time_meter.SetFilename("img/menus/stamina_bar.png");
00336 if (!VideoManager->LoadImage(_universal_time_meter))
00337 cerr << "BATTLE ERROR: Failed to load time meter." << endl;
00338
00339 _victory_items.clear();
00340
00341 _actor_selection_image.SetDimensions(109, 78);
00342 _actor_selection_image.SetFilename("img/icons/battle/character_selector.png");
00343 if (!VideoManager->LoadImage(_actor_selection_image)) {
00344 cerr << "BATTLE ERROR: Unable to load player selector image." << endl;
00345 }
00346
00347 _action_window = new ActionWindow();
00348 _finish_window = new FinishWindow();
00349 _TEMP_LoadTestData();
00350 }
00351
00352
00353
00354 BattleMode::~BattleMode() {
00355
00356 if (current_battle == this) {
00357 current_battle = NULL;
00358 }
00359
00360 for (uint32 i = 0; i < _battle_music.size(); i++)
00361 _battle_music.at(i).FreeMusic();
00362
00363
00364 for (deque<BattleCharacterActor*>::iterator i = _character_actors.begin(); i != _character_actors.end(); i++) {
00365 delete *i;
00366 }
00367 _character_actors.clear();
00368
00369 for (deque<BattleEnemyActor*>::iterator i = _enemy_actors.begin(); i != _enemy_actors.end(); i++) {
00370 delete *i;
00371 }
00372 _enemy_actors.clear();
00373
00374
00375 for (std::list<ScriptEvent*>::iterator i = _script_queue.begin(); i != _script_queue.end(); i++) {
00376 if ((*i)->GetItem())
00377 {
00378 (*i)->GetItem()->IncrementCount(1);
00379 }
00380 delete *i;
00381 }
00382 _script_queue.clear();
00383
00384 _victory_items.clear();
00385
00386
00387 VideoManager->DeleteImage(_battle_background);
00388 VideoManager->DeleteImage(_bottom_menu_image);
00389 VideoManager->DeleteImage(_actor_selection_image);
00390 VideoManager->DeleteImage(_attack_point_indicator);
00391 VideoManager->DeleteImage(_swap_icon);
00392 VideoManager->DeleteImage(_swap_card);
00393 VideoManager->DeleteImage(_universal_time_meter);
00394
00395
00396 delete(_action_window);
00397 delete(_finish_window);
00398 }
00399
00400
00401
00402 void BattleMode::Reset() {
00403 current_battle = this;
00404
00405 VideoManager->SetCoordSys(0.0f, 1024.0f, 0.0f, 768.0f);
00406 VideoManager->SetFont("battle");
00407
00408
00409 if (_battle_music.empty()) {
00410
00411 if (BATTLE_DEBUG) cerr << "BATTLE DEBUG: No music defined. Attempting to load the default theme" << endl;
00412
00413 MusicDescriptor MD;
00414 if (MD.LoadMusic("mus/Confrontation.ogg") == false) {
00415 cerr << "BATTLE ERROR: failed to load default battle theme track: " << MD.GetFilename() << endl;
00416 }
00417 else {
00418 _battle_music.push_back(MD);
00419 }
00420 }
00421
00422 if (_battle_music.empty() == false && _battle_music.back().IsPlaying() == false) {
00423 _battle_music.back().PlayMusic();
00424 }
00425
00426 if (_initialized == false) {
00427 _Initialize();
00428 }
00429 }
00430
00431
00432
00433 void BattleMode::AddEnemy(GlobalEnemy new_enemy) {
00434
00435 if (new_enemy.GetID() == 0) {
00436 if (BATTLE_DEBUG) {
00437 cerr << "BATTLE WARNING: attempted to add a new enemy with an invalid id (0). "
00438 << "The enemy was not added to the battle." << endl;
00439 }
00440 return;
00441 }
00442 if (new_enemy.GetExperienceLevel() != 0) {
00443 if (BATTLE_DEBUG) {
00444 cerr << "BATTLE WARNING: attempted to add a new enemy that had already been initialized to experience level "
00445 << new_enemy.GetExperienceLevel() << ". The enemy was not added to the battle." << endl;
00446 }
00447 }
00448
00449
00450 new_enemy.Initialize(GlobalManager->AverageActivePartyExperienceLevel());
00451
00452
00453 _original_enemies.push_back(new_enemy);
00454
00455
00456 float x = MONSTER_LOCATIONS[_next_monster_location_index][0];
00457 float y = MONSTER_LOCATIONS[_next_monster_location_index][1];
00458 _next_monster_location_index++;
00459
00460
00461
00462
00463
00464 _next_monster_location_index = _next_monster_location_index % 8;
00465
00466 BattleEnemyActor* enemy_actor= new BattleEnemyActor(new_enemy, x, y);
00467 enemy_actor->InitBattleActorStats(&new_enemy);
00468 _enemy_actors.push_back(enemy_actor);
00469 }
00470
00471
00472
00473 void BattleMode::AddMusic(string music_filename) {
00474 if (music_filename == "") {
00475 if (BATTLE_DEBUG)
00476 cerr << "BATTLE DEBUG: Passed in an empty music filename." << endl;
00477 return;
00478 }
00479
00480 MusicDescriptor MD;
00481 if (MD.LoadMusic(music_filename) == false) {
00482 cerr << "BATTLE ERROR: BattleMode::AddMusic failed to load this music file: " << music_filename << endl;
00483 }
00484 else {
00485 _battle_music.push_back(MD);
00486 }
00487 }
00488
00489
00490
00491 void BattleMode::_TEMP_LoadTestData() {
00492
00493 _battle_background.SetFilename("img/backdrops/battle/desert_cave.png");
00494 _battle_background.SetDimensions(SCREEN_LENGTH * TILE_SIZE, SCREEN_HEIGHT * TILE_SIZE);
00495 if (!VideoManager->LoadImage(_battle_background)) {
00496 cerr << "BATTLE ERROR: Failed to load background image: " << endl;
00497 _ShutDown();
00498 }
00499
00500 _bottom_menu_image.SetFilename("img/menus/battle_bottom_menu.png");
00501 _bottom_menu_image.SetDimensions(1024, 128);
00502 if (!VideoManager->LoadImage(_bottom_menu_image)) {
00503 cerr << "BATTLE ERROR: Failed to load bottom menu image: " << endl;
00504 _ShutDown();
00505 }
00506
00507 _swap_icon.SetFilename("img/icons/battle/swap_icon.png");
00508 _swap_icon.SetDimensions(35, 30);
00509 if (!VideoManager->LoadImage(_swap_icon)) {
00510 cerr << "BATTLE ERROR: Failed to load swap icon: " << endl;
00511 _ShutDown();
00512 }
00513
00514 _swap_card.SetFilename("img/icons/battle/swap_card.png");
00515 _swap_card.SetDimensions(25, 37);
00516 if (!VideoManager->LoadImage(_swap_card)) {
00517 cerr << "BATTLE ERROR: Failed to load swap card: " << endl;
00518 _ShutDown();
00519 }
00520 }
00521
00522
00523
00524 void BattleMode::_Initialize()
00525 {
00526
00527 GlobalParty* active_party = GlobalManager->GetActiveParty();
00528 if (active_party->GetPartySize() == 0) {
00529 if (BATTLE_DEBUG)
00530 cerr << "BATTLE ERROR: In BattleMode::_Initialize(), the size of the active party was zero" << endl;
00531 ModeManager->Pop();
00532 return;
00533 }
00534
00535
00536 for (uint32 i = 0; i < active_party->GetPartySize(); i++) {
00537 GlobalCharacter* new_character = dynamic_cast<GlobalCharacter*>(active_party->GetActorAtIndex(i));
00538 BattleCharacterActor* new_actor = new BattleCharacterActor(new_character, 256, 320);
00539 new_actor->InitBattleActorStats(new_character);
00540 _character_actors.push_back(new_actor);
00541 _selected_character = new_actor;
00542 }
00543
00544 _selected_character_index = GetIndexOfFirstIdleCharacter();
00545
00546
00547 for (uint8 i = 0; i < _enemy_actors.size(); i++) {
00548 if (_enemy_actors[i]->GetAgility() < _min_agility)
00549 _min_agility = _enemy_actors[i]->GetAgility();
00550 }
00551
00552 for (uint8 i = 0; i < _character_actors.size(); i++) {
00553 if (_character_actors[i]->GetAgility() < _min_agility)
00554 _min_agility = _character_actors[i]->GetAgility();
00555 }
00556
00557
00558
00559
00560 float proportion;
00561
00562 for (uint8 i = 0; i < _enemy_actors.size(); ++i)
00563 {
00564 proportion = static_cast<float>(_min_agility) / static_cast<float>(_enemy_actors[i]->GetAgility());
00565 _enemy_actors[i]->GetWaitTime()->SetDuration(static_cast<uint32>(MAX_INIT_WAIT_TIME * proportion));
00566
00567
00568
00569 _enemy_actors[i]->ResetWaitTime();
00570 }
00571
00572 for (uint8 i = 0; i < _character_actors.size(); ++i)
00573 {
00574 proportion = static_cast<float>(_min_agility) / static_cast<float>(_character_actors[i]->GetAgility());
00575 _character_actors[i]->GetWaitTime()->SetDuration(static_cast<uint32>(MAX_INIT_WAIT_TIME * proportion));
00576
00577
00578
00579 _character_actors[i]->ResetWaitTime();
00580 }
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 SystemManager->UpdateTimers();
00604
00605
00606
00607
00608
00609
00610 _initialized = true;
00611 }
00612
00613
00614
00615 void BattleMode::_ShutDown() {
00616 _battle_music[0].StopMusic();
00617
00618 for (uint32 i = 0; i < _character_actors.size(); ++i) {
00619 _character_actors[i]->UpdateGlobalActorStats();
00620 }
00621
00622
00623 InputManager->EventHandler();
00624
00625
00626 ModeManager->Pop();
00627 }
00628
00629
00630
00631 void BattleMode::_TallyRewards() {
00632 GlobalEnemy *gbe;
00633
00634 std::map<string, uint32>::iterator it;
00635 std::map<uint32, GlobalObject*>::iterator it2;
00636
00637 _victory_sp = GetNumberOfEnemies();
00638 for (uint32 i = 0; i < GetNumberOfEnemies(); ++i)
00639 {
00640 gbe = GetEnemyActorAt(i)->GetActor();
00641 _victory_xp += gbe->GetExperiencePoints();
00642 _victory_money += gbe->GetDrunesDropped();
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663 }
00664
00665 uint32 num_alive = 0;
00666
00667 for (uint32 i = 0; i < GetNumberOfCharacters(); ++i)
00668 {
00669 if (GetPlayerCharacterAt(i)->IsAlive())
00670 ++num_alive;
00671 }
00672
00673
00674 _victory_xp /= num_alive;
00675 }
00676
00678
00680
00681 void BattleMode::Update() {
00682 _battle_over = (_NumberEnemiesAlive() == 0) || (_NumberCharactersAlive() == 0);
00683 _victorious_battle = (_NumberEnemiesAlive() == 0);
00684
00685
00686 if (_battle_over) {
00687 if (_finish_window->GetState() == FINISH_INVALID) {
00688 _action_window->Reset();
00689 _finish_window->Initialize(_victorious_battle);
00690
00691 if (_victorious_battle) {
00692 _TallyRewards();
00693 PlayerVictory();
00694 }
00695 }
00696
00697
00698
00699 _finish_window->Update();
00700
00701
00702 return;
00703 }
00704
00705
00706 for (uint8 i = 0; i < _character_actors.size(); i++) {
00707 _character_actors[i]->Update();
00708 }
00709 for (uint8 i = 0; i < _enemy_actors.size(); i++) {
00710 _enemy_actors[i]->Update();
00711 }
00712
00713
00714 if (_script_queue.size()) {
00715
00716 std::list<private_battle::ScriptEvent*>::iterator it;
00717 bool ran_script = false;
00718 ScriptEvent* se;
00719
00720 for (it = _script_queue.begin(); it != _script_queue.end(); it++)
00721 {
00722 se = (*it);
00723 se->Update();
00724
00725
00726 if (se->GetWarmUpTime()->IsFinished() && !_IsPerformingScript())
00727 {
00728 SetPerformingScript(true,se);
00729 se->RunScript();
00730 ran_script = true;
00731
00732
00733 }
00734 }
00735
00736
00737 if (ran_script)
00738 {
00739
00740
00741
00742
00743 SetPerformingScript(false,NULL);
00744 }
00745 }
00746
00747
00748 if (_cursor_state == CURSOR_SELECT_ATTACK_POINT) {
00749 _attack_point_indicator.Update();
00750 }
00751
00752
00753 switch (_cursor_state) {
00754 case CURSOR_IDLE:
00755 _UpdateCharacterSelection();
00756 break;
00757 case CURSOR_WAIT:
00758 break;
00759 case CURSOR_SELECT_TARGET:
00760 _UpdateTargetSelection();
00761 break;
00762 case CURSOR_SELECT_ATTACK_POINT:
00763 _UpdateAttackPointSelection();
00764 break;
00765
00766 case CURSOR_SELECT_PARTY:
00767 default:
00768 break;
00769 }
00770
00771
00772 if (_action_window->GetState() != VIEW_INVALID)
00773 _action_window->Update();
00774 }
00775
00776
00777
00778 void BattleMode::_UpdateCharacterSelection() {
00779
00780 _selected_character_index = GetIndexOfFirstIdleCharacter();
00781 if (_selected_character_index == static_cast<int32>(INVALID_BATTLE_ACTOR_INDEX)) {
00782 return;
00783 }
00784
00785
00786
00787 if (ACTIVE_BATTLE_MODE == false)
00788 FreezeTimers();
00789
00790
00791 if (_NumberCharactersAlive() == 1) {
00792 _cursor_state = CURSOR_WAIT;
00793 _selected_character = GetPlayerCharacterAt(_selected_character_index);
00794 _action_window->Initialize(_selected_character);
00795 return;
00796 }
00797
00798
00799
00800
00801
00802
00803
00804 if (InputManager->UpPress() || InputManager->RightPress()) {
00805
00806
00807 uint32 working_index = _selected_character_index;
00808 BattleCharacterActor *bca;
00809
00810 while (working_index < GetNumberOfCharacters()) {
00811 bca = GetPlayerCharacterAt(working_index + 1);
00812 if (bca->IsAlive() && bca->GetWaitTime()->IsFinished() && !bca->IsQueuedToPerform()) {
00813 _selected_character_index = working_index + 1;
00814 break;
00815 }
00816
00817 ++working_index;
00818 }
00819 }
00820 else if (InputManager->DownPress() || InputManager->LeftPress()) {
00821
00822
00823 uint32 working_index = _selected_character_index;
00824 BattleCharacterActor *bca;
00825
00826 while (working_index > 0) {
00827 bca = GetPlayerCharacterAt(working_index + 1);
00828 if (bca->IsAlive() && bca->GetWaitTime()->IsFinished() && !bca->IsQueuedToPerform())
00829 {
00830 _selected_character_index = working_index - 1;
00831 break;
00832 }
00833 --working_index;
00834 }
00835 }
00836 else if (InputManager->ConfirmPress()) {
00837 _cursor_state = CURSOR_WAIT;
00838 _selected_character = GetPlayerCharacterAt(_selected_character_index);
00839 _action_window->Initialize(_selected_character);
00840 }
00841 }
00842
00843
00844
00845 void BattleMode::_UpdateTargetSelection() {
00846 if (InputManager->DownPress() || InputManager->LeftPress()) {
00847 if (_action_window->GetActionTargetType() != GLOBAL_TARGET_PARTY) {
00848 if (_action_window->IsActionTargetAlly()) {
00849 if (InputManager->DownPress()) {
00850 if (_selected_target->IsEnemy() == false) {
00851 if (_selected_target_index) {
00852 --_selected_target_index;
00853 }
00854 else {
00855 _selected_target_index = GlobalManager->GetActiveParty()->GetPartySize() - 1;
00856 }
00857 _selected_target = GetPlayerCharacterAt(_selected_target_index);
00858 }
00859 else {
00860 _selected_target_index = GetIndexOfNextAliveEnemy(false);
00861 _selected_target = GetEnemyActorAt(_selected_target_index);
00862 }
00863 }
00864 }
00865 else {
00866 _selected_target_index = GetIndexOfNextAliveEnemy(false);
00867 _selected_target = GetEnemyActorAt(_selected_target_index);
00868 }
00869 }
00870 }
00871
00872 else if (InputManager->UpPress() || InputManager->RightPress()) {
00873 if (_action_window->GetActionTargetType() != GLOBAL_TARGET_PARTY) {
00874 if (_action_window->IsActionTargetAlly()) {
00875 if (InputManager->UpPress()) {
00876 if (_selected_target->IsEnemy() == false) {
00877 if (_selected_target_index < GlobalManager->GetActiveParty()->GetPartySize() - 1) {
00878 ++_selected_target_index;
00879 }
00880 else {
00881 _selected_target_index = 0;
00882 }
00883
00884 _selected_target = GetPlayerCharacterAt(_selected_target_index);
00885 }
00886 else {
00887 _selected_target_index = GetIndexOfNextAliveEnemy(true);
00888 _selected_target = GetEnemyActorAt(_selected_target_index);
00889 }
00890 }
00891 }
00892 else {
00893 _selected_target_index = GetIndexOfNextAliveEnemy(true);
00894 _selected_target = GetEnemyActorAt(_selected_target_index);
00895 }
00896 }
00897
00898 }
00899
00900 else if (InputManager->ConfirmPress()) {
00901 if (_action_window->GetActionTargetType() == GLOBAL_TARGET_ATTACK_POINT) {
00902 _cursor_state = CURSOR_SELECT_ATTACK_POINT;
00903
00904 _selected_attack_point = 0;
00905 }
00906 else {
00907
00908 ScriptEvent* new_event;
00909 if (_action_window->GetActionCategory() != ACTION_TYPE_ITEM) {
00910 new_event = new ScriptEvent(_selected_character, _selected_target, _action_window->GetSelectedSkill());
00911 }
00912 else {
00913 GlobalItem* item = _action_window->GetSelectedItem();
00914
00915
00916
00917
00918
00919 item->DecrementCount(1);
00920 new_event = new ScriptEvent(_selected_character, _selected_target, item);
00921 }
00922 AddScriptEventToQueue(new_event);
00923 _selected_character->SetQueuedToPerform(true);
00924 _selected_target = NULL;
00925 _selected_character_index = GetIndexOfFirstIdleCharacter();
00926 _cursor_state = CURSOR_IDLE;
00927
00928
00929 if (ACTIVE_BATTLE_MODE == false)
00930 UnFreezeTimers();
00931 }
00932 }
00933
00934 else if (InputManager->CancelPress()) {
00935 _cursor_state = CURSOR_IDLE;
00936 _selected_target = NULL;
00937 }
00938 }
00939
00940
00941
00942 void BattleMode::_UpdateAttackPointSelection() {
00943 BattleEnemyActor* e = GetEnemyActorAt(_selected_target_index);
00944 vector<GlobalAttackPoint*>* global_attack_points = e->GetActor()->GetAttackPoints();
00945
00946 if (InputManager->ConfirmPress()) {
00947 ScriptEvent* new_event;
00948 if (_action_window->GetActionCategory() != ACTION_TYPE_ITEM) {
00949 new_event = new ScriptEvent(_selected_character, _selected_target, _action_window->GetSelectedSkill(),
00950 global_attack_points->at(_selected_attack_point));
00951 }
00952 else {
00953 GlobalItem* item = _action_window->GetSelectedItem();
00954
00955
00956
00957
00958
00959 item->DecrementCount(1);
00960 new_event = new ScriptEvent(_selected_character, _selected_target, item, global_attack_points->at(_selected_attack_point));
00961 }
00962 AddScriptEventToQueue(new_event);
00963 _selected_character->SetQueuedToPerform(true);
00964 _selected_target = NULL;
00965 _selected_character_index = GetIndexOfFirstIdleCharacter();
00966 _cursor_state = CURSOR_IDLE;
00967 _action_window->Reset();
00968
00969
00970 if (ACTIVE_BATTLE_MODE == false)
00971 UnFreezeTimers();
00972 }
00973
00974 else if (InputManager->UpPress() || InputManager->RightPress()) {
00975 if (_selected_attack_point < global_attack_points->size() - 1) {
00976 _selected_attack_point++;
00977 }
00978 else if (_selected_attack_point == global_attack_points->size() - 1) {
00979 _selected_attack_point = 0;
00980 }
00981 }
00982
00983 else if (InputManager->DownPress() || InputManager->LeftPress()) {
00984 if (_selected_attack_point > 0) {
00985 _selected_attack_point--;
00986 }
00987 else if (_selected_attack_point == 0) {
00988 _selected_attack_point = global_attack_points->size() - 1;
00989 }
00990 }
00991
00992 else if (InputManager->CancelPress()) {
00993 _cursor_state = CURSOR_SELECT_TARGET;
00994 }
00995 }
00996
00998
01000
01001 void BattleMode::Draw() {
01002
01003 if (_battle_over) {
01004 if (_victorious_battle) {
01005 VideoManager->EnableSceneLighting(Color(0.914f, 0.753f, 0.106f, 1.0f));
01006 }
01007 else {
01008 VideoManager->EnableSceneLighting(Color(1.0f, 0.0f, 0.0f, 1.0f));
01009 }
01010 }
01011
01012 _DrawBackgroundVisuals();
01013 _DrawBottomMenu();
01014 _DrawSprites();
01015 _DrawTimeMeter();
01016
01017 if (_action_window->GetState() != VIEW_INVALID) {
01018 _action_window->Draw();
01019 }
01020
01021 if (_battle_over) {
01022 _finish_window->Draw();
01023 }
01024 }
01025
01026
01027
01028 void BattleMode::_DrawBackgroundVisuals() {
01029
01030 VideoManager->SetDrawFlags(VIDEO_X_LEFT, VIDEO_Y_BOTTOM, VIDEO_NO_BLEND, 0);
01031 VideoManager->Move(0, 0);
01032 VideoManager->DrawImage(_battle_background);
01033
01034
01035 }
01036
01037
01038
01039 void BattleMode::_DrawBottomMenu() {
01040
01041 VideoManager->SetDrawFlags(VIDEO_X_LEFT, VIDEO_Y_BOTTOM, VIDEO_BLEND, 0);
01042 VideoManager->Move(0, 0);
01043 VideoManager->DrawImage(_bottom_menu_image);
01044
01045
01046 VideoManager->Move(6, 16);
01047 VideoManager->DrawImage(_swap_icon, Color::gray);
01048 VideoManager->Move(6, 68);
01049 for (uint8 i = 0; i < _current_number_swaps; i++) {
01050 VideoManager->DrawImage(_swap_card);
01051 VideoManager->MoveRelative(4, -4);
01052 }
01053
01054
01055 _selected_character->DrawPortrait();
01056
01057
01058 for (uint32 i = 0; i < _character_actors.size(); i++) {
01059 _character_actors[i]->DrawStatus();
01060 }
01061 }
01062
01063
01064
01065 void BattleMode::_DrawSprites() {
01066
01067
01068
01069 for (uint32 i = 0; i < _character_actors.size(); i++) {
01070 _character_actors[i]->DrawSprite();
01071 }
01072
01073
01074
01075
01076
01077 for (uint32 i = 0; i < _enemy_actors.size(); i++) {
01078 _enemy_actors[i]->DrawSprite();
01079 }
01080 }
01081
01082
01083
01084 void BattleMode::_DrawTimeMeter() {
01085 VideoManager->SetDrawFlags(VIDEO_X_LEFT, VIDEO_Y_BOTTOM, 0);
01086 VideoManager->Move(1010, 128);
01087 VideoManager->DrawImage(_universal_time_meter);
01088
01089 VideoManager->SetDrawFlags(VIDEO_X_CENTER, VIDEO_Y_CENTER, 0);
01090
01091
01092 GLOBAL_TARGET target_type = GLOBAL_TARGET_INVALID;
01093 bool selected;
01094
01095 if (_cursor_state == CURSOR_SELECT_TARGET || _cursor_state == CURSOR_SELECT_ATTACK_POINT)
01096 {
01097 if (_action_window->GetActionCategory() == ACTION_TYPE_ITEM)
01098 {
01099 target_type = _action_window->GetActionTargetType();
01100 }
01101
01102 else
01103 {
01104
01105
01106 }
01107 }
01108
01109
01110 for (uint32 i = 0; i < _character_actors.size(); i++)
01111 {
01112 selected = false;
01113
01114 if (_cursor_state == CURSOR_SELECT_TARGET || _cursor_state == CURSOR_SELECT_ATTACK_POINT)
01115 {
01116
01117
01118
01119 if (target_type == GLOBAL_TARGET_PARTY)
01120 {
01121 if (!_selected_target->IsEnemy())
01122 {
01123 selected = true;
01124 }
01125 }
01126 else
01127 {
01128 if (!_selected_target->IsEnemy() && _selected_target == _character_actors[i])
01129 {
01130 selected = true;
01131 }
01132 }
01133 }
01134
01135 _character_actors[i]->DrawTimePortrait(selected);
01136 }
01137
01138
01139
01140 for (uint32 i = 0; i < _enemy_actors.size(); i++)
01141 {
01142 selected = false;
01143
01144 if (_cursor_state == CURSOR_SELECT_TARGET || _cursor_state == CURSOR_SELECT_ATTACK_POINT)
01145 {
01146
01147
01148
01149 if (target_type == GLOBAL_TARGET_PARTY)
01150 {
01151 if (_selected_target->IsEnemy())
01152 {
01153 selected = true;
01154 }
01155 }
01156 else
01157 {
01158 if (_selected_target->IsEnemy() && _selected_target == _enemy_actors[i])
01159 {
01160 selected = true;
01161 }
01162 }
01163 }
01164 _enemy_actors[i]->DrawTimePortrait(selected);
01165 }
01166 }
01167
01169
01171
01172 bool _TEMPIsA1Smaller(BattleEnemyActor* a1, BattleEnemyActor* a2) {
01173 if (a1->GetYLocation() - a1->GetActor()->GetSpriteHeight() < a2->GetYLocation() - a2->GetActor()->GetSpriteHeight())
01174 return true;
01175
01176 return false;
01177 }
01178
01179
01180
01181 struct AscendingYSort {
01182 bool operator()(BattleEnemyActor* a1, BattleEnemyActor* a2)
01183 {
01184
01185 return _TEMPIsA1Smaller(a1, a2);
01186 }
01187 };
01188
01189
01190
01191 uint32 BattleMode::_NumberEnemiesAlive() const {
01192 uint32 enemy_count = 0;
01193 for (uint32 i = 0; i < _enemy_actors.size(); i++) {
01194 if (_enemy_actors[i]->IsAlive()) {
01195 enemy_count++;
01196 }
01197 }
01198 return enemy_count;
01199 }
01200
01201
01202
01203 uint32 BattleMode::_NumberCharactersAlive() const {
01204 uint32 character_count = 0;
01205 for (uint32 i = 0; i < _character_actors.size(); i++) {
01206 if (_character_actors[i]->IsAlive()) {
01207 character_count++;
01208 }
01209 }
01210 return character_count;
01211 }
01212
01213
01214
01215 void BattleMode::SetPerformingScript(bool is_performing, ScriptEvent* se) {
01216
01217
01218
01219 if (!is_performing) {
01220
01221
01222
01223
01224 BattleActor* source = (*_active_se).GetSource();
01225 if (source) {
01226 source->SetQueuedToPerform(false);
01227
01228
01229 std::list<private_battle::ScriptEvent*>::iterator it = _script_queue.begin();
01230 while (it != _script_queue.end()) {
01231 if ((*it) == _active_se) {
01232 _script_queue.erase(it);
01233 break;
01234 }
01235 it++;
01236 }
01237
01238
01239
01240
01241 source->ResetWaitTime();
01242 _active_se = NULL;
01243 }
01244 else {
01245 cerr << "Invalid IBattleActor pointer in SetPerformingScript()" << endl;
01246 SystemManager->ExitGame();
01247 }
01248 }
01249 else {
01250 if (se == NULL) {
01251 cerr << "Invalid IBattleActor pointer in SetPerformingScript()" << endl;
01252 SystemManager->ExitGame();
01253 }
01254 }
01255
01256 _performing_script = is_performing;
01257 _active_se = se;
01258 }
01259
01260
01261
01262 void BattleMode::RemoveScriptedEventsForActor(BattleActor * actor) {
01263
01264 std::list<private_battle::ScriptEvent*>::iterator it = _script_queue.begin();
01265
01266 while (it != _script_queue.end()) {
01267 if ((*it)->GetSource() == actor) {
01268 if ((*it)->GetItem())
01269 (*it)->GetItem()->IncrementCount(1);
01270 it = _script_queue.erase(it);
01271 }
01272 else {
01273 it++;
01274 }
01275 }
01276 }
01277
01278 void BattleMode::FreezeTimers()
01279 {
01280 std::list<private_battle::ScriptEvent*>::iterator it = _script_queue.begin();
01281
01282 while (it != _script_queue.end())
01283 {
01284 if ((*it)->GetWarmUpTime()->IsRunning())
01285 (*it)->GetWarmUpTime()->Pause();
01286
01287 ++it;
01288 }
01289
01290
01291 for (uint32 i = 0; i < _character_actors.size(); ++i)
01292 {
01293 if (_character_actors.at(i)->GetWaitTime()->IsRunning())
01294 _character_actors.at(i)->GetWaitTime()->Pause();
01295 }
01296
01297
01298 for (uint32 i = 0; i < _enemy_actors.size(); ++i)
01299 {
01300 if (_enemy_actors.at(i)->GetWaitTime()->IsRunning())
01301 _enemy_actors.at(i)->GetWaitTime()->Pause();
01302 }
01303 }
01304
01305
01306 void BattleMode::UnFreezeTimers()
01307 {
01308
01309
01310 std::list<private_battle::ScriptEvent*>::iterator it = _script_queue.begin();
01311
01312 while (it != _script_queue.end())
01313 {
01314 if ((*it)->GetWarmUpTime()->IsPaused())
01315 (*it)->GetWarmUpTime()->Run();
01316
01317 ++it;
01318 }
01319
01320
01321 for (uint32 i = 0; i < _character_actors.size(); ++i)
01322 {
01323 if (_character_actors.at(i)->GetWaitTime()->IsPaused())
01324 _character_actors.at(i)->GetWaitTime()->Run();
01325 }
01326
01327
01328 for (uint32 i = 0; i < _enemy_actors.size(); ++i)
01329 {
01330 if (_enemy_actors.at(i)->GetWaitTime()->IsPaused())
01331 _enemy_actors.at(i)->GetWaitTime()->Run();
01332 }
01333 }
01334
01335
01336
01337 void BattleMode::PlayerVictory() {
01338 GlobalManager->AddDrunes(_victory_money);
01339
01340 for (uint32 i = 0; i < _character_actors.size(); ++i) {
01341 GlobalCharacter* character = _character_actors.at(i)->GetActor();
01342 if (character->GetExperienceForNextLevel() < _victory_xp) {
01343 _victory_level = true;
01344
01345 if (character->GetExperienceLevel() == 1) {
01346 _victory_skill = true;
01347 character->AddSkill(2);
01348 }
01349 }
01350
01351 character->AddExperiencePoints(_victory_xp);
01352 _character_actors.at(i)->SetSkillPoints(_character_actors.at(i)->GetSkillPoints() + _victory_sp);
01353 }
01354 }
01355
01356
01357
01358 void BattleMode::PlayerDefeat() {
01359 _ShutDown();
01360 ModeManager->PopAll();
01361 BootMode *BM = new BootMode();
01362 ModeManager->Push(BM);
01363 }
01364
01365
01366
01367 void BattleMode::SwapCharacters(BattleCharacterActor * ActorToRemove, BattleCharacterActor * ActorToAdd) {
01368
01369 for (std::deque < BattleCharacterActor * >::iterator it = _character_actors.begin(); it != _character_actors.end(); it++) {
01370 if (*it == ActorToRemove) {
01371 _character_actors.erase(it);
01372 break;
01373 }
01374 }
01375
01376
01377 ActorToAdd->SetXOrigin(ActorToRemove->GetXOrigin());
01378 ActorToAdd->SetYOrigin(ActorToRemove->GetYOrigin());
01379 ActorToAdd->SetXLocation(static_cast<float>(ActorToRemove->GetXOrigin()));
01380 ActorToAdd->SetYLocation(static_cast<float>(ActorToRemove->GetYOrigin()));
01381
01382 _character_actors.push_back(ActorToAdd);
01383 }
01384
01385
01386
01387 uint32 BattleMode::GetIndexOfFirstAliveEnemy() const {
01388 std::deque<private_battle::BattleEnemyActor*>::const_iterator it = _enemy_actors.begin();
01389 for (uint32 i = 0; it != _enemy_actors.end(); i++, it++) {
01390 if ((*it)->IsAlive()) {
01391 return i;
01392 }
01393 }
01394
01395
01396 return INVALID_BATTLE_ACTOR_INDEX;
01397 }
01398
01399
01400 uint32 BattleMode::GetIndexOfLastAliveEnemy() const {
01401 std::deque<private_battle::BattleEnemyActor*>::const_iterator it = _enemy_actors.end()-1;
01402 for (int32 i = _enemy_actors.size()-1; i >= 0; i--, it--) {
01403 if ((*it)->IsAlive()) {
01404 return i;
01405 }
01406 }
01407
01408
01409 return INVALID_BATTLE_ACTOR_INDEX;
01410 }
01411
01412
01413
01414 uint32 BattleMode::GetIndexOfFirstIdleCharacter() const {
01415 BattleCharacterActor *bca;
01416 deque<BattleCharacterActor*>::const_iterator it = _character_actors.begin();
01417
01418 for (uint32 i = 0; it != _character_actors.end(); i++, it++) {
01419 bca = (*it);
01420 if (!bca->IsQueuedToPerform() && bca->GetActor()->IsAlive() && bca->GetWaitTime()->IsFinished())
01421 {
01422 return i;
01423 }
01424 }
01425
01426 return INVALID_BATTLE_ACTOR_INDEX;
01427 }
01428
01429
01430
01431 uint32 BattleMode::GetIndexOfCharacter(BattleCharacterActor * const Actor) const {
01432 deque<BattleCharacterActor*>::const_iterator it = _character_actors.begin();
01433 for (int32 i = 0; it != _character_actors.end(); i++, it++) {
01434 if (*it == Actor)
01435 return i;
01436 }
01437
01438
01439 return INVALID_BATTLE_ACTOR_INDEX;
01440 }
01441
01442
01443
01444 uint32 BattleMode::GetIndexOfNextAliveEnemy(bool move_upward) const {
01445
01446
01447 if (move_upward)
01448 {
01449 for (uint32 i = _selected_target_index + 1; i < _enemy_actors.size(); ++i)
01450 {
01451 if (_enemy_actors[i]->IsAlive())
01452 {
01453 return i;
01454 }
01455 }
01456 for (uint32 i = 0; i <= _selected_target_index; ++i)
01457 {
01458 if (_enemy_actors[i]->IsAlive())
01459 {
01460 return i;
01461 }
01462 }
01463
01464
01465 return INVALID_BATTLE_ACTOR_INDEX;
01466 }
01467 else
01468 {
01469 for (int32 i = static_cast<int32>(_selected_target_index) - 1; i >= 0; --i)
01470 {
01471 if (_enemy_actors[i]->IsAlive())
01472 {
01473 return i;
01474 }
01475 }
01476 for (int32 i = static_cast<int32>(_enemy_actors.size()) - 1; i >= static_cast<int32>(_selected_target_index); --i)
01477 {
01478 if (_enemy_actors[i]->IsAlive())
01479 {
01480 return i;
01481 }
01482 }
01483
01484
01485 return INVALID_BATTLE_ACTOR_INDEX;
01486 }
01487 }
01488
01489 }