battle.cpp

Go to the documentation of this file.
00001 
00002 //            Copyright (C) 2004-2007 by The Allacrost Project
00003 //                         All Rights Reserved
00004 //
00005 // This code is licensed under the GNU GPL version 2. It is free software and
00006 // you may modify it and/or redistribute it under the terms of this license.
00007 // See http://www.gnu.org/copyleft/gpl.html for details.
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 // SCRIPTEVENT CLASS
00058 
00059 //ScriptEvent::ScriptEvent(hoa_global::GlobalActor * source, std::deque<IBattleActor*> targets, const std::string & script_name) :
00060 /*ScriptEvent::ScriptEvent(BattleActor* source, std::deque<BattleActor*> targets, const std::string & script_name, uint32 warm_up_time) :
00061   _script_name(script_name),
00062   _source(source),
00063   _skill(NULL),
00064   _item(NULL),
00065   _targets(targets)
00066 {
00067   _warm_up_time.SetDuration(warm_up_time);
00068   _warm_up_time.Reset();
00069   _warm_up_time.Play();
00070 }*/
00071 
00072 //Constructor for a script event that uses an item
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 // Constructor for a script event that uses an item
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 // Constructor with multiple targets and a skill
00099 /*ScriptEvent::ScriptEvent(BattleActor* source, std::deque<BattleActor*> targets, hoa_global::GlobalSkill* skill) :
00100   _source(source),
00101   _skill(skill),
00102   _item(NULL),
00103   _targets(targets),
00104   _target(NULL)
00105 {
00106   _warm_up_time.Initialize(skill->GetWarmupTime());
00107   _warm_up_time.Run();
00108 }*/
00109 
00110 
00111 ScriptEvent::~ScriptEvent()
00112 {
00113 }
00114 
00115 
00116 void ScriptEvent::Update()
00117 {
00118   //_warm_up_time -= SystemManager->GetUpdateTime();
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   //TODO Any warm up animations
00126 }
00127 
00128 void ScriptEvent::RunScript() {
00129   //If _item is non-NULL, then we're using an item
00130   if (_item)
00131   {
00132     if (_item->GetTargetType() == GLOBAL_TARGET_PARTY)
00133     {
00134       if (_target->IsEnemy())
00135       {
00136         BattleEnemyActor* bea;
00137         //Loop through enemies and apply the item
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         //_item->DecrementCount(1);
00152 
00153         /*if (_item->GetCount() == 0)
00154         {
00155           GlobalManager->RemoveFromInventory(_item->GetID());
00156         }*/
00157       }
00158       else
00159       {
00160         BattleCharacterActor* bca;
00161         //Loop through all party members and apply
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         //_item->DecrementCount(1);
00176 
00177         /*if (_item->GetCount() == 0)
00178         {
00179           GlobalManager->RemoveFromInventory(_item->GetID());
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       //_item->DecrementCount(1);
00191 
00192       /*if (_item->GetCount() == 0)
00193       {
00194         GlobalManager->RemoveFromInventory(_item->GetID());
00195       }*/
00196       //FIX ME Reconstruct action list somehow (do via ran_script)
00197     }
00198 
00199     if (_item->GetCount() == 0)
00200     {
00201       GlobalManager->RemoveFromInventory(_item->GetID());
00202     }
00203   }
00204   // TEMP: do basic damage to the actors
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         //Loop through enemies and apply the item
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         //Loop through all party members and apply
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       //if (_target)
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       else
00261       {
00262         _skill->BattleExecute(current_battle->GetPlayerCharacterAt(0), _source);
00263       }*/
00264     }
00265 
00266     _source->SetSkillPoints(_source->GetSkillPoints() - _skill->GetSPRequired());
00267   }
00268 
00269   //FIXE ME Temp code!!!
00270   if (_source)
00271   {
00272     _source->TEMP_ResetAttackTimer();
00273     //if (_source->IsEnemy())
00274     //{
00275     //  dynamic_cast<BattleEnemyActor*>(_source)->ResetAttackTimer();
00276     //}
00277   }
00278 }
00279 
00280 } // namespace private battle
00281 
00282 
00284 // BattleMode class -- Initialization and Destruction Code
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), // 5 minutes
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   //Load the universal time meter image
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 } // BattleMode::BattleMode()
00351 
00352 
00353 
00354 BattleMode::~BattleMode() {
00355   // Don't let current_battle keep pointing to this object instance any longer
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   // Delete all character and enemy actors
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   // FIX ME: If item scripts are still there, add the item back to the inventory
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   // Remove all of the battle images that were loaded
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   // Delete all GUI objects that are allocated
00396   delete(_action_window);
00397   delete(_finish_window);
00398 } // BattleMode::~BattleMode()
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   // Load the default battle music track if no other music has been added
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 } // void BattleMode::Reset()
00430 
00431 
00432 
00433 void BattleMode::AddEnemy(GlobalEnemy new_enemy) {
00434   // (1): Don't add the enemy if it has an invalid ID or an experience level that is not zero
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   // (2): Level the enemy up to be within a reasonable range of the party's strength
00450   new_enemy.Initialize(GlobalManager->AverageActivePartyExperienceLevel());
00451 
00452   // (3): Hold a copy of this enemy in case the battle needs to be restarted
00453   _original_enemies.push_back(new_enemy);
00454 
00455   // (4): Construct the enemy battle actor to be placed on the battle field
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   // TEMP
00461   // The next line modulus have been changed. Howeever, a better solution is to provide a std::vector
00462   // instead of an array for MONSTER_LOCATIONS, init in the constructor, and make modulus with the vector length
00463   // _next_monster_location_index = _next_monster_location_index % (sizeof(MONSTER_LOCATIONS)/2); <-- Before
00464   _next_monster_location_index = _next_monster_location_index % 8;  // <-- Now
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   // Load all background images
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   // (1): Construct all character battle actors from the active party
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(); // Self-destruct the battle mode
00532     return;
00533   }
00534   // TODO: implement this later
00535   // COMMENT: Implement what later?
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   // (2) Loop through and find the actor with the lowest agility
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   //Now adjust starting wait times based on agility proportions
00558   //If current actor's agility is twice the lowest agility, then
00559   //they will have a wait time that is half of the slowest actor
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     //Start the timer.  We can do this here because the calculations will be done so quickly
00568     //that the other chars wont fall far behind.
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     //Start the timer.  We can do this here because the calculations will be done so quickly
00578     //that the other chars wont fall far behind.
00579     _character_actors[i]->ResetWaitTime();
00580   }
00581 
00582   // Andy: Once every game loop, the SystemManager's timers are updated
00583   // However, in between calls, battle mode is constructed. As part
00584   // of battle mode's construction, each actor is given a wait timer
00585   // that is triggered on initialization. But the moving of the stamina
00586   // portrait uses the update time from SystemManager.  Therefore, the
00587   // amount of time since SystemManager last updated is greater than
00588   // the amount of time that has expired on the actors' wait timers
00589   // during the first orund of battle mode.  This gives the portrait an
00590   // extra boost, so once the wait time expires for an actor, his portrait
00591   // is past the designated stopping point
00592 
00593   // <--      time       -->
00594   // A----------X-----------B
00595   // If the SystemManager has its timers updated at A and B, and battle mode is
00596   // constructed and initialized at X, you can see the amount of time between
00597   // X and B (how much time passed on the wait timers in round 1) is significantly
00598   // smaller than the time between A and B.  Hence the extra boost to the stamina
00599   // portrait's location
00600 
00601   //FIX ME This will not work in the future (i.e. paralysis)...realized this
00602   //after writing all the above crap
00603   SystemManager->UpdateTimers();
00604 
00605   //TEMP: For testing battle item usage only!  Pull once usage is proven!
00606   // Adds a health potion to your inventory
00607   //GlobalManager->AddToInventory(1);
00608   //_action_type_menu.EnableOption(3,true);
00609 
00610   _initialized = true;
00611 } // void BattleMode::_Initialize()
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   // This call will clear the input state
00623   InputManager->EventHandler();
00624 
00625   // Remove this BattleMode instance from the game stack
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   //Tally up the xp, money, and get the list of items
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   // Roots: this code is now defunct. Refer to the GlobalEnemy class to determine items dropped
00645 //    if (RandomFloat() * 100 <= gbe->GetChanceToDrop())
00646 //    {
00647 //      //Added here so that we can display the list on victory
00648 //      //FIX ME later
00649 //      GlobalManager->AddToInventory(gbe->GetItemDropped());
00650 // 
00651 //      it2 = GlobalManager->GetInventory()->find(gbe->GetItemDropped());
00652 //      it = _victory_items.find(MakeStandardString(it2->second->GetName()));
00653 // 
00654 //      if (it != _victory_items.end())
00655 //      {
00656 //        ++it->second;
00657 //      }
00658 //      else
00659 //      {
00660 //        _victory_items.insert(make_pair(MakeStandardString(it2->second->GetName()), 1));
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   //Divvy the XP between surviving party members
00674   _victory_xp /= num_alive;
00675 }
00676 
00678 // BattleMode class -- Update Code
00680 
00681 void BattleMode::Update() {
00682   _battle_over = (_NumberEnemiesAlive() == 0) || (_NumberCharactersAlive() == 0);
00683   _victorious_battle = (_NumberEnemiesAlive() == 0);
00684 
00685   // ----- (1): If the battle is over, only execute this small block of update code
00686   if (_battle_over) {
00687     if (_finish_window->GetState() == FINISH_INVALID) { // Indicates that the battle has just now finished
00688       _action_window->Reset();
00689       _finish_window->Initialize(_victorious_battle);
00690 
00691       if (_victorious_battle) {
00692         _TallyRewards();
00693         PlayerVictory();
00694       }
00695     }
00696 
00697     // The FinishWindow::Update() function handles all update code when a battle is over.
00698     // The call to shut down battle mode is also made from within this call.
00699     _finish_window->Update();
00700 
00701     // Do not update other battle code if the battle has already ended
00702     return;
00703   } // if (_battle_over)
00704 
00705   // ----- (2): Update the state of all battle actors
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   // ----- (3): Execute any scripts that are sitting in the queue
00714   if (_script_queue.size()) {
00715   //if (!_IsPerformingScript() && _script_queue.size() > 0) {
00716     std::list<private_battle::ScriptEvent*>::iterator it;
00717     bool ran_script = false;
00718     ScriptEvent* se;
00719     //for (uint8 i = 0; i < _script_queue.size(); i++)
00720     for (it = _script_queue.begin(); it != _script_queue.end(); it++)
00721     {
00722       se = (*it);//_script_queue.front();
00723       se->Update();
00724       //(*it).Update();
00725       //se._warm_up_time -= SystemManager->GetUpdateTime();
00726       if (se->GetWarmUpTime()->IsFinished() && !_IsPerformingScript())
00727       {
00728         SetPerformingScript(true,se);
00729         se->RunScript();
00730         ran_script = true;
00731         //Later have battle mode call UpdateActiveScriptEvent instead
00732         //_script_queue.pop_front();
00733       }
00734     }
00735 
00736     //Do this out here so iterator doesnt get screwed up mid-loop
00737     if (ran_script)
00738     {
00739       //If we used an item, immediately reconstruct the action list
00740       //This way if an item is used
00741       //if (se->GetItem())
00742 
00743       SetPerformingScript(false,NULL);
00744     }
00745   } // if (_script_queue.size())
00746 
00747   // ----- (4): Update various menus and other GUI graphics as appropriate
00748   if (_cursor_state == CURSOR_SELECT_ATTACK_POINT) {
00749     _attack_point_indicator.Update();
00750   }
00751 
00752   // ----- (5): Process user input depending upon which state the menu cursor is in
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     // TODO: What should be done for these two options?
00766     case CURSOR_SELECT_PARTY:
00767     default:
00768       break;
00769   } // switch (_cursor_state)
00770 
00771   // ----- (6): Update the action window if the player is making an action or target selection
00772   if (_action_window->GetState() != VIEW_INVALID)
00773     _action_window->Update();
00774 } // void BattleMode::Update()
00775 
00776 
00777 
00778 void BattleMode::_UpdateCharacterSelection() {
00779   // First check if there are any characters in the idle state. If there aren't, there's nothing left to do
00780   _selected_character_index = GetIndexOfFirstIdleCharacter();
00781   if (_selected_character_index == static_cast<int32>(INVALID_BATTLE_ACTOR_INDEX)) {
00782     return;
00783   }
00784 
00785   // TODO: Only freeze timers this when we've gone from having no idle characters to having at least one idle character
00786   // If the battle is running in wait mode, freeze all timers while the player selects an action
00787   if (ACTIVE_BATTLE_MODE == false)
00788     FreezeTimers();
00789 
00790   // If there is only one character alive, then we are sure that he/she is the character to select
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   // TODO: the code below doesn't work very well in practice (fight a battle with two characters and see what I mean)
00799   // it needs to be cleaned
00800 
00801   // Otherwise there are multiple characters, of which more than one may be idle
00802 
00803   // Handle user input commands: up, down, left, right, confirm
00804   if (InputManager->UpPress() || InputManager->RightPress()) {
00805     // Select the next character above the currently selected one
00806     // If no such character exists, the selected character will remain selected
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     // Select the next character below the currently selected one.
00822     // If no such character exists, the selected character will remain selected
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 } // void BattleMode::_UpdateCharacterSelection()
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       } // if (_action_window->IsActionTargetAlly())
00865       else {
00866         _selected_target_index = GetIndexOfNextAliveEnemy(false);
00867         _selected_target = GetEnemyActorAt(_selected_target_index);
00868       }
00869     }
00870   } // if (InputManager->DownPress() || InputManager->LeftPress())
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       } // if (_action_window->IsActionTargetAlly())
00892       else {
00893         _selected_target_index = GetIndexOfNextAliveEnemy(true);
00894         _selected_target = GetEnemyActorAt(_selected_target_index);
00895       }
00896     }
00897 
00898   } // else if (InputManager->UpPress() || InputManager->RightPress())
00899 
00900   else if (InputManager->ConfirmPress()) {
00901     if (_action_window->GetActionTargetType() == GLOBAL_TARGET_ATTACK_POINT) {
00902       _cursor_state = CURSOR_SELECT_ATTACK_POINT;
00903       // TODO: Implement cursor memory for attack points here
00904       _selected_attack_point = 0;
00905     }
00906     else {
00907       // Create the script event to execute
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         // NOTE: Don't know if decrementing the item count is the best approach to use here.
00915         // We decrement the count now so that if the next character wants to use items, they know
00916         // how many are available to use. If the current chararacter uses the item, then the decrement stays.
00917         // If count == 0, then it's removed from inventory...if item is not used (i.e. battle ends before use),
00918         // it is incremented back.
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       // Resume battle timers if the battle is executing in wait mode
00929       if (ACTIVE_BATTLE_MODE == false)
00930         UnFreezeTimers();
00931     }
00932   } // else if (InputManager->ConfirmPress())
00933 
00934   else if (InputManager->CancelPress()) {
00935     _cursor_state = CURSOR_IDLE;
00936     _selected_target = NULL;
00937   }
00938 } // void BattleMode::_UpdateTargetSelection()
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       // NOTE: Don't know if decrementing the item count is the best approach to use here.
00955       // We decrement the count now so that if the next character wants to use items, they know
00956       // how many are available to use. If the current chararacter uses the item, then the decrement stays.
00957       // If count == 0, then it's removed from inventory...if item is not used (i.e. battle ends before use),
00958       // it is incremented back.
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     // Resume battle timers if the battle is executing in wait mode
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 } // void BattleMode::_UpdateAttackPointSelection()
00996 
00998 // BattleMode class -- Draw Code
01000 
01001 void BattleMode::Draw() {
01002   // Apply scene lighting if the battle has finished
01003   if (_battle_over) {
01004     if (_victorious_battle) {
01005       VideoManager->EnableSceneLighting(Color(0.914f, 0.753f, 0.106f, 1.0f)); // Golden color for victory
01006     }
01007     else {
01008       VideoManager->EnableSceneLighting(Color(1.0f, 0.0f, 0.0f, 1.0f)); // Red color for defeat
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 } // void BattleMode::Draw()
01025 
01026 
01027 
01028 void BattleMode::_DrawBackgroundVisuals() {
01029   // Draw the full-screen, static background image
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   // TODO: Draw other background objects and animations
01035 } // void BattleMode::_DrawBackgroundVisuals()
01036 
01037 
01038 
01039 void BattleMode::_DrawBottomMenu() {
01040   // Draw the static image for the lower menu
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   // Draw the swap icon and any swap cards
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   // Draw the selected character's portrait, blended according to the character's current HP level
01055   _selected_character->DrawPortrait();
01056 
01057   // Draw the status information of all character actors
01058   for (uint32 i = 0; i < _character_actors.size(); i++) {
01059     _character_actors[i]->DrawStatus();
01060   }
01061 } // void BattleMode::_DrawBottomMenu()
01062 
01063 
01064 
01065 void BattleMode::_DrawSprites() {
01066   // TODO: Draw sprites in order based on their x and y coordinates on the screen (bottom to top, then left to right)
01067 
01068   // Draw all character sprites
01069   for (uint32 i = 0; i < _character_actors.size(); i++) {
01070     _character_actors[i]->DrawSprite();
01071   }
01072 
01073   // Sort and draw the enemies
01074   //std::deque<private_battle::BattleEnemyActor*> sorted_enemy_actors = _enemy_actors;
01075   //std::sort(sorted_enemy_actors.begin(), sorted_enemy_actors.end(), AscendingYSort());
01076 
01077   for (uint32 i = 0; i < _enemy_actors.size(); i++) {
01078     _enemy_actors[i]->DrawSprite();
01079   }
01080 } // void BattleMode::_DrawSprites()
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   // Draw all character portraits
01089   VideoManager->SetDrawFlags(VIDEO_X_CENTER, VIDEO_Y_CENTER, 0);
01090   //BattleEnemyActor * e = GetEnemyActorAt(_selected_target_index);
01091 
01092   GLOBAL_TARGET target_type = GLOBAL_TARGET_INVALID;
01093   bool selected;// = false;
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     //FIX ME Work in option for flee
01102     else
01103     {
01104       //FIX ME
01105 //      target_type = action_window->GetActionTargetType();
01106     }
01107   }
01108 
01109   //FIX ME Below is the logic that should be used...requires change to UpdateTargetSelection code
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       //FIX ME Temp code.  Instead, check chosen item or skill's
01117       //Target Type.  If PARTY and _selected_target is a BattleCharacterActor,
01118       //loop through and highlight all characters
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   // Draw all enemy sprites
01139   // FIX ME use some logic for targeting highlight, loop on _selected_actor_arguments
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       //FIX ME Temp code.  Instead, check chosen item or skill's
01147       //Target Type.  If PARTY and _selected_target is a BattleCharacterActor,
01148       //loop through and highlight all characters
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 } // void BattleMode::_DrawTimeMeter()
01167 
01169 // BattleMode class -- Miscellaneous Code
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 // Ascending Y sorting functor. We want to compare the actual objects, NOT pointers!
01181 struct AscendingYSort {
01182   bool operator()(BattleEnemyActor* a1, BattleEnemyActor* a2)
01183   {
01184     //return ((*a1) < (*a2));
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 // Sets whether an action is being performed or not
01215 void BattleMode::SetPerformingScript(bool is_performing, ScriptEvent* se) {
01216   // Check if a script has just ended. Set the script to stop performing and pop the script from the front of the queue
01217   // ANDY: Only one script will be running at a time, so only need to check the incoming bool
01218 
01219   if (!is_performing) { // == false && _performing_script == true)
01220     // Remove the first scripted event from the queue
01221     // _script_queue.front().GetSource() is always either BattleEnemyActor or BattleCharacterActor
01222     //IBattleActor * source = dynamic_cast<IBattleActor*>(_script_queue.front().GetSource());
01223     //IBattleActor* source = _script_queue.front().GetSource();
01224     BattleActor* source = (*_active_se).GetSource();
01225     if (source) {
01226       source->SetQueuedToPerform(false);
01227       //ScriptEvent t = *_active_se;
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       //_script_queue.erase(_active_se);
01238       //_script_queue.pop_front();
01239       //_script_queue.remove(t);
01240       //FIX ME Use char and enemy stats
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 {// if (is_performing && !_performing_script)
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 //void BattleMode::RemoveScriptedEventsForActor(IBattleActor * actor) {
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); //remove this location
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   //Pause scripts
01282   while (it != _script_queue.end())
01283   {
01284     if ((*it)->GetWarmUpTime()->IsRunning())
01285       (*it)->GetWarmUpTime()->Pause();
01286 
01287     ++it;
01288   }
01289 
01290   //Pause characters
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   //Pause enemies
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   //FIX ME Do not unpause timers for paralyzed actors
01309   //Unpause scripts
01310   std::list<private_battle::ScriptEvent*>::iterator it = _script_queue.begin();
01311   //Pause scripts
01312   while (it != _script_queue.end())
01313   {
01314     if ((*it)->GetWarmUpTime()->IsPaused())
01315       (*it)->GetWarmUpTime()->Run();
01316 
01317     ++it;
01318   }
01319 
01320   //Unpause characters
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   //Unpause enemies
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 // Handle player victory
01337 void BattleMode::PlayerVictory() {
01338   GlobalManager->AddDrunes(_victory_money);
01339   // Give some experience for each character in the party
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 //      AudioManager->PlaySound("snd/level_up.wav");
01345       if (character->GetExperienceLevel() == 1) { // Character is upgrading to level 2
01346         _victory_skill = true;
01347         character->AddSkill(2);
01348       }
01349     }
01350     // ROOTS: This function returns a bool indicating if there was any character growth... needs to be checked
01351     character->AddExperiencePoints(_victory_xp);
01352     _character_actors.at(i)->SetSkillPoints(_character_actors.at(i)->GetSkillPoints() + _victory_sp);
01353   }
01354 }
01355 
01356 
01357 // Handle player defeat
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   // Remove 'ActorToRemove'
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   // set location and origin to removing characters location and origin
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);  //add the other character to battle
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   //Should not be reached
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   //Should not be reached
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   //Should not be reached
01439   return INVALID_BATTLE_ACTOR_INDEX;
01440 }
01441 
01442 
01443 
01444 uint32 BattleMode::GetIndexOfNextAliveEnemy(bool move_upward) const {
01445   //BattleCharacterActor *bca;
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     //Should never be reached
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     //Should never be reached
01485     return INVALID_BATTLE_ACTOR_INDEX;
01486   }
01487 }
01488 
01489 } // namespace hoa_battle

Generated on Fri Jul 6 23:11:10 2007 for Hero of Allacrost by  doxygen 1.5.1