global_actors.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
00006 // and 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 
00016 #include <iostream>
00017 
00018 #include "utils.h"
00019 #include "video.h"
00020 #include "script.h"
00021 
00022 #include "global.h"
00023 
00024 using namespace std;
00025 
00026 using namespace hoa_utils;
00027 using namespace hoa_video;
00028 using namespace hoa_script;
00029 
00030 namespace hoa_global {
00031 
00032 // -----------------------------------------------------------------------------
00033 // GlobalAttackPoint class
00034 // -----------------------------------------------------------------------------
00035 
00036 bool GlobalAttackPoint::_LoadData(ReadScriptDescriptor& script) {
00037   if (script.IsFileOpen() == false) {
00038     return false;
00039   }
00040 
00041   _name = MakeUnicodeString(script.ReadString("name"));
00042   _x_position = script.ReadInt("x_position");
00043   _y_position = script.ReadInt("y_position");
00044   _fortitude_modifier = script.ReadFloat("fortitude_modifier");
00045   _protection_modifier = script.ReadFloat("protection_modifier");
00046   _evade_modifier = script.ReadFloat("evade_modifier");
00047 
00048   if (script.IsErrorDetected()) {
00049     if (GLOBAL_DEBUG) {
00050       cerr << "GLOBAL ERROR: GlobalAttackPoint::LoadData() failed due to script reading errors. "
00051         << "They are as follows:" << endl;
00052       cerr << script.GetErrorMessages() << endl;
00053     }
00054     return false;
00055   }
00056 
00057   return true;
00058 } // bool GlobalAttackPoint::_LoadData(ReadScriptDescriptor& script)
00059 
00060 // -----------------------------------------------------------------------------
00061 // GlobalActor class
00062 // -----------------------------------------------------------------------------
00063 
00064 GlobalActor::~GlobalActor() {
00065   // Delete all attack points
00066   for (uint32 i = 0; i < _attack_points.size(); i++) {
00067     delete _attack_points[i];
00068   }
00069   _attack_points.clear();
00070 
00071   // Delete all equipment
00072   if (_weapon_equipped != NULL)
00073     delete _weapon_equipped;
00074   for (uint32 i = 0; i < _armor_equipped.size(); i++) {
00075     if (_armor_equipped[i] != NULL)
00076       delete _armor_equipped[i];
00077   }
00078   _armor_equipped.clear();
00079 
00080   // Delete all skills
00081   for (map<uint32, GlobalSkill*>::iterator i = _skills.begin(); i != _skills.end(); i++) {
00082     delete i->second;
00083   }
00084   _skills.clear();
00085 }
00086 
00087 
00088 
00089 uint32 GlobalActor::GetTotalPhysicalDefense(uint32 index) const {
00090   if (index >= _attack_points.size()) {
00091     if (GLOBAL_DEBUG)
00092       cerr << "GLOBAL WARNING: GlobalActor::GetTotalPhysicalDefense() was called with an invalid "
00093         << "index argument: " << index << endl;
00094     return 0;
00095   }
00096   else {
00097     return _attack_points[index]->GetTotalPhysicalDefense();
00098   }
00099 }
00100 
00101 
00102 
00103 uint32 GlobalActor::GetTotalMetaphysicalDefense(uint32 index) const {
00104   if (index >= _attack_points.size()) {
00105     if (GLOBAL_DEBUG)
00106       cerr << "GLOBAL WARNING: GlobalActor::GetTotalMetaphysicalDefense() was called with an invalid "
00107         << "index argument: " << index << endl;
00108     return 0;
00109   }
00110   else {
00111     return _attack_points[index]->GetTotalMetaphysicalDefense();
00112   }
00113 }
00114 
00115 
00116 
00117 float GlobalActor::GetTotalEvadeRating(uint32 index) const {
00118   if (index >= _attack_points.size()) {
00119     if (GLOBAL_DEBUG)
00120       cerr << "GLOBAL WARNING: GlobalActor::GetTotalEvadeRating() was called with an invalid "
00121         << "index argument: " << index << endl;
00122     return 0.0f;
00123   }
00124   else {
00125     return _attack_points[index]->GetTotalEvadeRating();
00126   }
00127 }
00128 
00129 
00130 
00131 GlobalArmor* GlobalActor::GetArmorEquipped(uint32 index) const {
00132   if (index >= _armor_equipped.size()) {
00133     if (GLOBAL_DEBUG)
00134       cerr << "GLOBAL WARNING: GlobalActor::GetArmorEquipped() was called with an invalid "
00135         << "index argument: " << index << endl;
00136     return NULL;
00137   }
00138   else {
00139     return _armor_equipped[index];
00140   }
00141 }
00142 
00143 
00144 
00145 GlobalAttackPoint* GlobalActor::GetAttackPoint(uint32 index) const {
00146   if (index >= _attack_points.size()) {
00147     if (GLOBAL_DEBUG)
00148       cerr << "GLOBAL WARNING: GlobalActor::GetAttackPoint() was called with an invalid "
00149         << "index argument: " << index << endl;
00150     return NULL;
00151   }
00152   else {
00153     return _attack_points[index];
00154   }
00155 }
00156 
00157 
00158 
00159 GlobalSkill* GlobalActor::GetSkill(uint32 skill_id) const {
00160   map<uint32, GlobalSkill*>::const_iterator skill_location = _skills.find(skill_id);
00161   if (skill_location != _skills.end())
00162     return skill_location->second;
00163   else
00164     return NULL;
00165 }
00166 
00167 
00168 
00169 GlobalSkill* GlobalActor::GetSkill(const GlobalSkill* skill) const {
00170   if (skill == NULL) {
00171     if (GLOBAL_DEBUG)
00172       cerr << "GLOBAL WARNING: GlobalActor::GetSkill() was called with a NULL skill argument" << endl;
00173     return NULL;
00174   }
00175   return GetSkill(skill->GetID());
00176 }
00177 
00178 
00179 
00180 void GlobalActor::_CalculateAttackRatings() {
00181   _total_physical_attack = _strength;
00182   _total_metaphysical_attack = _vigor;
00183 
00184   if (_weapon_equipped != NULL) {
00185     _total_physical_attack += _weapon_equipped->GetPhysicalAttack();
00186     _total_metaphysical_attack += _weapon_equipped->GetMetaphysicalAttack();
00187   }
00188 }
00189 
00190 
00191 
00192 void GlobalActor::_CalculateDefenseRatings() {
00193   // Re-calculate the defense ratings for all attack points
00194   for (uint32 i = 0; i < _attack_points.size(); i++) {
00195     // If the modifier is -100% or less, set the total defense to zero
00196     _attack_points[i]->_total_physical_defense = 0;
00197     if (_attack_points[i]->_fortitude_modifier > -1.0f)
00198       _attack_points[i]->_total_physical_defense = _fortitude + static_cast<uint32>(_fortitude * _attack_points[i]->_fortitude_modifier);
00199 
00200     _attack_points[i]->_total_metaphysical_defense = 0;
00201     if (_attack_points[i]->_protection_modifier > -1.0f)
00202       _attack_points[i]->_total_metaphysical_defense = _protection + static_cast<uint32>(_protection * _attack_points[i]->_protection_modifier);
00203 
00204     // If there's armor equipped on this attack point add its defensive properties to the defense totals
00205     if (_armor_equipped[i] != NULL) {
00206       _attack_points[i]->_total_physical_defense += _armor_equipped[i]->GetPhysicalDefense();
00207       _attack_points[i]->_total_metaphysical_defense += _armor_equipped[i]->GetMetaphysicalDefense();
00208     }
00209   }
00210 } // void GlobalActor::_CalculateDefenseRatings()
00211 
00212 
00213 
00214 void GlobalActor::_CalculateEvadeRatings() {
00215   // Re-calculate the evade ratings for all attack points
00216   for (uint32 i = 0; i < _attack_points.size(); i++) {
00217     // If the modifier is -100% or less, set the evade rating to zero
00218     _attack_points[i]->_total_evade_rating = 0;
00219     if (_attack_points[i]->_evade_modifier > -1.0f)
00220       _attack_points[i]->_total_evade_rating = _evade + static_cast<uint32>(_evade * _attack_points[i]->_evade_modifier);
00221   }
00222 } // void GlobalActor::_CalculateEvadeRatings()
00223 
00224 
00225 
00226 GlobalWeapon* GlobalActor::EquipWeapon(GlobalWeapon* weapon) {
00227   GlobalWeapon* old_weapon = _weapon_equipped;
00228   _weapon_equipped = weapon;
00229   _CalculateAttackRatings();
00230   return old_weapon;
00231 }
00232 
00233 
00234 
00235 GlobalArmor* GlobalActor::EquipArmor(GlobalArmor* armor, uint32 index) {
00236   if (index < _armor_equipped.size()) {
00237     if (GLOBAL_DEBUG)
00238       cerr << "GLOBAL ERROR: GlobalActor::EquipArmor() was given an invalid index: " << index
00239         << ", the armor was not equipped" << endl;
00240     return armor;
00241   }
00242 
00243   GlobalArmor* old_armor = _armor_equipped[index];
00244   _armor_equipped[index] = armor;
00245 
00246   if (old_armor != NULL && armor != NULL) {
00247     if (old_armor->GetObjectType() != armor->GetObjectType()) {
00248       if (GLOBAL_DEBUG)
00249         cerr << "GLOBAL WARNING: GlobalActor::EquipArmor() replaced the old armor "
00250           << "with a different type of armor" << endl;
00251     }
00252   }
00253   _CalculateDefenseRatings();
00254   return old_armor;
00255 }
00256 
00257 // -----------------------------------------------------------------------------
00258 // GlobalCharacterGrowth class
00259 // -----------------------------------------------------------------------------
00260 
00261 GlobalCharacterGrowth::~GlobalCharacterGrowth() {
00262   for (list<GlobalSkill*>::iterator i = _skills_learned.begin(); i != _skills_learned.end();) {
00263     delete (*i);
00264     i = _skills_learned.erase(i);
00265   }
00266 }
00267 
00268 
00269 
00270 void GlobalCharacterGrowth::AcknowledgeGrowth() {
00271   if (_growth_detected == false) {
00272     if (GLOBAL_DEBUG)
00273       cerr << "GLOBAL WARNING: GlobalCharacterGrowth::AcknowledgeGrowth() was invoked when there was no character "
00274         << "growth detected" << endl;
00275     return;
00276   }
00277 
00278   _growth_detected = false;
00279   _hit_points_growth = 0;
00280   _skill_points_growth = 0;
00281   _strength_growth = 0;
00282   _vigor_growth = 0;
00283   _fortitude_growth = 0;
00284   _protection_growth = 0;
00285   _agility_growth = 0;
00286   _evade_growth = 0.0f;
00287 
00288   // If a new experience level has been gained, we must retrieve the growth data for the new experience level
00289   if (_experience_level_gained) {
00290     _character_owner->_experience_level += 1;
00291     _experience_level_gained = false;
00292     _DetermineNextLevelExperience();
00293 
00294     ReadScriptDescriptor character_script;
00295     if (character_script.OpenFile("dat/characters.lua") == false) {
00296       if (GLOBAL_DEBUG)
00297         cerr << "GLOBAL ERROR: GlobalCharacterGrowth::AcknowledgeGrowth() failed to open the script file containing the "
00298           << "character's definition when the character reached a new experience level" << endl;
00299       return;
00300     }
00301 
00302     try {
00303       ScriptCallFunction<void>(character_script.GetLuaState(), "DetermineGrowth", this);
00304       _ConstructPeriodicGrowth();
00305       _CheckForGrowth();
00306     }
00307     catch (luabind::error e) {
00308       ScriptManager->HandleLuaError(e);
00309     }
00310     catch (luabind::cast_failed e) {
00311       ScriptManager->HandleCastError(e);
00312     }
00313   } // if (_experience_level_gained)
00314 } // void GlobalCharacterGrowth::AcknowledgeGrowth()
00315 
00316 
00317 
00318 void GlobalCharacterGrowth::_AddSkill(uint32 skill_id) {
00319   if (skill_id == 0) {
00320     if (GLOBAL_DEBUG)
00321       cerr << "GLOBAL WARNING: GlobalCharacterGrowth::_AddSkill() failed because an invalid skill id was passed to it (0)" << endl;
00322     return;
00323   }
00324 
00325   // Make sure we don't add a skill to learn more than once
00326   for (list<GlobalSkill*>::iterator i = _skills_learned.begin(); i != _skills_learned.end(); i++) {
00327     if (skill_id == (*i)->GetID()) {
00328       if (GLOBAL_DEBUG)
00329         cerr << "GLOBAL WARNING: GlobalCharacterGrowth::_AddSkill() failed because the skill to be added was already "
00330           << "present in the list of skills to earn. The skill ID in question was: " << skill_id << endl;
00331       return;
00332     }
00333   }
00334 
00335   GlobalSkill* skill = new GlobalSkill(skill_id);
00336   if (skill->GetID() == 0) { // Indicates that the skill failed to load successfully
00337     if (GLOBAL_DEBUG)
00338       cerr << "GLOBAL WARNING: GlobalCharacterGrowth::_AddSkill() failed because the skill failed to load" << endl;
00339     delete skill;
00340   }
00341   else {
00342     _skills_learned.push_back(skill);
00343   }
00344 } // void GlobalCharacterGrowth::_AddSkill(uint32 skill_id)
00345 
00346 
00347 
00348 void GlobalCharacterGrowth::_CheckForGrowth() {
00349   // ----- (1): If a new experience level is gained, empty the periodic growth containers into the growth members
00350   if (_character_owner->GetExperiencePoints() >= _experience_for_next_level) {
00351     _experience_level_gained = true;
00352     _growth_detected = true;
00353 
00354     for (uint32 i = 0; i < _hit_points_periodic_growth.size(); i++)
00355       _hit_points_growth += _hit_points_periodic_growth[i].second;
00356     _hit_points_periodic_growth.clear();
00357 
00358     for (uint32 i = 0; i < _skill_points_periodic_growth.size(); i++)
00359       _skill_points_growth += _skill_points_periodic_growth[i].second;
00360     _skill_points_periodic_growth.clear();
00361 
00362     for (uint32 i = 0; i < _strength_periodic_growth.size(); i++)
00363       _strength_growth += _strength_periodic_growth[i].second;
00364     _strength_periodic_growth.clear();
00365 
00366     for (uint32 i = 0; i < _vigor_periodic_growth.size(); i++)
00367       _vigor_growth += _vigor_periodic_growth[i].second;
00368     _vigor_periodic_growth.clear();
00369 
00370     for (uint32 i = 0; i < _fortitude_periodic_growth.size(); i++)
00371       _fortitude_growth += _fortitude_periodic_growth[i].second;
00372     _fortitude_periodic_growth.clear();
00373 
00374     for (uint32 i = 0; i < _protection_periodic_growth.size(); i++)
00375       _protection_growth += _protection_periodic_growth[i].second;
00376     _protection_periodic_growth.clear();
00377 
00378     for (uint32 i = 0; i < _agility_periodic_growth.size(); i++)
00379       _agility_growth += _agility_periodic_growth[i].second;
00380     _agility_periodic_growth.clear();
00381 
00382     for (uint32 i = 0; i < _evade_periodic_growth.size(); i++)
00383       _evade_growth += _evade_periodic_growth[i].second;
00384     _evade_periodic_growth.clear();
00385 
00386     // Make a run through the skills to learn and make sure that the character does not already know that skill
00387     for (list<GlobalSkill*>::iterator i = _skills_learned.begin(); i != _skills_learned.end();) {
00388       if (_character_owner->GetSkill(*i) == NULL) { // If true then the skill to learn is not already known by the character
00389         i++;
00390       }
00391       else {
00392         if (GLOBAL_DEBUG)
00393           cerr << "GLOBAL WARNING: GlobalCharacterGrowth::_CheckForGrowth() detected that the character already knew the skill "
00394             << "that was to be learned on the next experience level. The ID of that skill was: " << (*i)->GetID() << endl;
00395         delete *i;
00396         i = _skills_learned.erase(i);
00397       }
00398     }
00399     
00400     return;
00401   } // if (_actor_ower->GetExperiencePoints() >= _experience_for_next_level)
00402 
00403   // ----- (2): If there is no growth detected, check all periodic growth containers
00404   switch (_growth_detected) { // switch statement used instead of if statement here so we can break out of it early
00405     case true:
00406       break;
00407     case false:
00408       if (_hit_points_periodic_growth.empty() == false) {
00409         if (_character_owner->GetExperiencePoints() >= _hit_points_periodic_growth.front().first) {
00410           _growth_detected = true;
00411           break;
00412         }
00413       }
00414 
00415       if (_skill_points_periodic_growth.empty() == false) {
00416         if (_character_owner->GetExperiencePoints() >= _skill_points_periodic_growth.front().first) {
00417           _growth_detected = true;
00418           break;
00419         }
00420       }
00421 
00422       if (_strength_periodic_growth.empty() == false) {
00423         if (_character_owner->GetExperiencePoints() >= _strength_periodic_growth.front().first) {
00424           _growth_detected = true;
00425           break;
00426         }
00427       }
00428 
00429       if (_vigor_periodic_growth.empty() == false) {
00430         if (_character_owner->GetExperiencePoints() >= _vigor_periodic_growth.front().first) {
00431           _growth_detected = true;
00432           break;
00433         }
00434       }
00435 
00436       if (_fortitude_periodic_growth.empty() == false) {
00437         if (_character_owner->GetExperiencePoints() >= _fortitude_periodic_growth.front().first) {
00438           _growth_detected = true;
00439           break;
00440         }
00441       }
00442 
00443       if (_protection_periodic_growth.empty() == false) {
00444         if (_character_owner->GetExperiencePoints() >= _protection_periodic_growth.front().first) {
00445           _growth_detected = true;
00446           break;
00447         }
00448       }
00449 
00450       if (_agility_periodic_growth.empty() == false) {
00451         if (_character_owner->GetExperiencePoints() >= _agility_periodic_growth.front().first) {
00452           _growth_detected = true;
00453           break;
00454         }
00455       }
00456 
00457       if (_evade_periodic_growth.empty() == false) {
00458         if (_character_owner->GetExperiencePoints() >= _evade_periodic_growth.front().first) {
00459           _growth_detected = true;
00460           break;
00461         }
00462       }
00463       break;
00464   } // switch (_growth_detected)
00465 
00466   // ----- (3): If there is no growth detected update all periodic growth containers
00467   if (_growth_detected == true) {
00468     while (_hit_points_periodic_growth.begin() != _hit_points_periodic_growth.end()) {
00469       if (_character_owner->GetExperiencePoints() >= _hit_points_periodic_growth.begin()->first) {
00470         _hit_points_growth += _hit_points_periodic_growth.begin()->second;
00471         _hit_points_periodic_growth.pop_front();
00472       }
00473       else {
00474         break;
00475       }
00476     }
00477 
00478     while (_skill_points_periodic_growth.begin() != _skill_points_periodic_growth.end()) {
00479       if (_character_owner->GetExperiencePoints() >= _skill_points_periodic_growth.begin()->first) {
00480         _skill_points_growth += _skill_points_periodic_growth.begin()->second;
00481         _skill_points_periodic_growth.pop_front();
00482       }
00483       else {
00484         break;
00485       }
00486     }
00487 
00488     while (_strength_periodic_growth.begin() != _strength_periodic_growth.end()) {
00489       if (_character_owner->GetExperiencePoints() >= _strength_periodic_growth.begin()->first) {
00490         _strength_growth += _strength_periodic_growth.begin()->second;
00491         _strength_periodic_growth.pop_front();
00492       }
00493       else {
00494         break;
00495       }
00496     }
00497 
00498     while (_vigor_periodic_growth.begin() != _vigor_periodic_growth.end()) {
00499       if (_character_owner->GetExperiencePoints() >= _vigor_periodic_growth.begin()->first) {
00500         _vigor_growth += _vigor_periodic_growth.begin()->second;
00501         _vigor_periodic_growth.pop_front();
00502       }
00503       else {
00504         break;
00505       }
00506     }
00507 
00508     while (_fortitude_periodic_growth.begin() != _fortitude_periodic_growth.end()) {
00509       if (_character_owner->GetExperiencePoints() >= _fortitude_periodic_growth.begin()->first) {
00510         _fortitude_growth += _fortitude_periodic_growth.begin()->second;
00511         _fortitude_periodic_growth.pop_front();
00512       }
00513       else {
00514         break;
00515       }
00516     }
00517 
00518     while (_protection_periodic_growth.begin() != _protection_periodic_growth.end()) {
00519       if (_character_owner->GetExperiencePoints() >= _protection_periodic_growth.begin()->first) {
00520         _protection_growth += _protection_periodic_growth.begin()->second;
00521         _protection_periodic_growth.pop_front();
00522       }
00523       else {
00524         break;
00525       }
00526     }
00527 
00528     while (_agility_periodic_growth.begin() != _agility_periodic_growth.end()) {
00529       if (_character_owner->GetExperiencePoints() >= _agility_periodic_growth.begin()->first) {
00530         _agility_growth += _agility_periodic_growth.begin()->second;
00531         _agility_periodic_growth.pop_front();
00532       }
00533       else {
00534         break;
00535       }
00536     }
00537 
00538     while (_evade_periodic_growth.begin() != _evade_periodic_growth.end()) {
00539       if (_character_owner->GetExperiencePoints() >= _evade_periodic_growth.begin()->first) {
00540         _evade_growth += _evade_periodic_growth.begin()->second;
00541         _evade_periodic_growth.pop_front();
00542       }
00543       else {
00544         break;
00545       }
00546     }
00547   } // if (_growth_detected == true)
00548 } // void GlobalCharacterGrowth::_CheckForGrowth()
00549 
00550 
00551 
00552 void GlobalCharacterGrowth::_ConstructPeriodicGrowth() {
00553   // TODO: Implement a gradual growth algorithm
00554 
00555   // TEMP: all growth is done when the experience level is gained
00556   _hit_points_periodic_growth.push_back(make_pair(_experience_for_next_level, _hit_points_growth));
00557   _skill_points_periodic_growth.push_back(make_pair(_experience_for_next_level, _skill_points_growth));
00558   _strength_periodic_growth.push_back(make_pair(_experience_for_next_level, _strength_growth));
00559   _vigor_periodic_growth.push_back(make_pair(_experience_for_next_level, _vigor_growth));
00560   _fortitude_periodic_growth.push_back(make_pair(_experience_for_next_level, _fortitude_growth));
00561   _protection_periodic_growth.push_back(make_pair(_experience_for_next_level, _protection_growth));
00562   _agility_periodic_growth.push_back(make_pair(_experience_for_next_level, _agility_growth));
00563   _evade_periodic_growth.push_back(make_pair(_experience_for_next_level, _evade_growth));
00564 
00565   _hit_points_growth = 0;
00566   _skill_points_growth = 0;
00567   _strength_growth = 0;
00568   _vigor_growth = 0;
00569   _fortitude_growth = 0;
00570   _protection_growth = 0;
00571   _agility_growth = 0;
00572   _evade_growth = 0.0f;
00573 } // void GlobalCharacterGrowth::_ConstructPeriodicGrowth()
00574 
00575 
00576 
00577 void GlobalCharacterGrowth::_DetermineNextLevelExperience() {
00578   uint32 new_xp = 0; // Temporary variable for holding the new experience milestone
00579 
00580   // TODO: implement a real algorithm for determining the next experience goal
00581   new_xp = _experience_for_last_level + 50;
00582 
00583   _experience_for_last_level = _experience_for_next_level;
00584   _experience_for_next_level = new_xp;
00585 } // void GlobalCharacterGrowth::_DetermineNextLevelExperience()
00586 
00587 // -----------------------------------------------------------------------------
00588 // GlobalCharacter class
00589 // -----------------------------------------------------------------------------
00590 
00591 GlobalCharacter::GlobalCharacter(uint32 id, bool initial) :
00592   _growth(this)
00593 {
00594   _id = id;
00595 
00596   // (1): Attempt to open the characters script file
00597   ReadScriptDescriptor char_script;
00598   if (char_script.OpenFile("dat/actors/characters.lua") == false) {
00599     if (GLOBAL_DEBUG)
00600       cerr << "GLOBAL ERROR: GlobalCharacter constructor could not create a new character because "
00601         << "the script file dat/actors/character.lua did not open succesfully" << endl;
00602     // Set the character's ID to zero since this is now an invalid character object
00603     _id = 0;
00604     return;
00605   }
00606 
00607   // (2): Open up the table containing the character's data and retrieve their basic properties
00608   char_script.OpenTable("characters");
00609   char_script.OpenTable(_id);
00610   _name = MakeUnicodeString(char_script.ReadString("name"));
00611   _filename = char_script.ReadString("filename");
00612 
00613   // (3): Constructing the character from their initial stats if requested
00614   if (initial) {
00615     char_script.OpenTable("initial_stats");
00616     _experience_level = char_script.ReadUInt("experience_level");
00617     _experience_points = char_script.ReadUInt("experience_points");
00618     _max_hit_points = char_script.ReadUInt("max_hit_points");
00619     _hit_points = _max_hit_points;
00620     _max_skill_points = char_script.ReadUInt("max_skill_points");
00621     _skill_points = _max_skill_points;
00622     _strength = char_script.ReadUInt("strength");
00623     _vigor = char_script.ReadUInt("vigor");
00624     _fortitude = char_script.ReadUInt("fortitude");
00625     _protection = char_script.ReadUInt("protection");
00626     _agility = char_script.ReadUInt("agility");
00627     _evade = char_script.ReadFloat("evade");
00628 
00629     // Add the character's initial equipment. If any equipment ids are zero, that indicates nothing is to be equipped.
00630     uint32 equipment_id = 0;
00631     equipment_id = char_script.ReadUInt("weapon");
00632     if (equipment_id != 0) {
00633       _weapon_equipped = new GlobalWeapon(equipment_id);
00634     } else {
00635       _weapon_equipped = NULL;
00636     }
00637 
00638     equipment_id = char_script.ReadUInt("head_armor");
00639     if (equipment_id != 0) {
00640       _armor_equipped.push_back(new GlobalArmor(equipment_id));
00641     } else {
00642       _armor_equipped.push_back(NULL);
00643     }
00644 
00645     equipment_id = char_script.ReadUInt("torso_armor");
00646     if (equipment_id != 0) {
00647       _armor_equipped.push_back(new GlobalArmor(equipment_id));
00648     } else {
00649       _armor_equipped.push_back(NULL);
00650     }
00651 
00652     equipment_id = char_script.ReadUInt("arm_armor");
00653     if (equipment_id != 0) {
00654       _armor_equipped.push_back(new GlobalArmor(equipment_id));
00655     } else {
00656       _armor_equipped.push_back(NULL);
00657     }
00658 
00659     equipment_id = char_script.ReadUInt("leg_armor");
00660     if (equipment_id != 0) {
00661       _armor_equipped.push_back(new GlobalArmor(equipment_id));
00662     } else {
00663       _armor_equipped.push_back(NULL);
00664     }
00665     char_script.CloseTable();
00666 
00667     if (char_script.IsErrorDetected()) {
00668       if (GLOBAL_DEBUG) {
00669         cerr << "GLOBAL WARNING: GlobalCharacter constructor had errors in reading the character's "
00670           << "initial stats. They are as follows:" << endl;
00671         cerr << char_script.GetErrorMessages() << endl;
00672       }
00673     }
00674   } // if (initial)
00675 
00676   // (4): Setup the character's attack points
00677   char_script.OpenTable("attack_points");
00678   for (uint32 i = GLOBAL_POSITION_HEAD; i < GLOBAL_POSITION_LEGS; i++) {
00679     _attack_points.push_back(new GlobalAttackPoint(this));
00680     char_script.OpenTable(i);
00681     if (_attack_points[i]->_LoadData(char_script) == false) {
00682       if (GLOBAL_DEBUG) {
00683         cerr << "GLOBAL WARNING: GlobalCharacter constructor failed to succesfully load data for "
00684           << "attack point number: " << i << endl;
00685       }
00686     }
00687     char_script.CloseTable();
00688   }
00689   char_script.CloseTable();
00690 
00691   if (char_script.IsErrorDetected()) {
00692     if (GLOBAL_DEBUG) {
00693       cerr << "GLOBAL WARNING: GlobalCharacter constructor had errors in reading the character's "
00694         << "attack points. They are as follows:" << endl;
00695       cerr << char_script.GetErrorMessages() << endl;
00696     }
00697   }
00698 
00699   // (5): Create the character's initial skill set, if requested
00700   if (initial) {
00701     // The keys to the skills table indicate the skill id, the value is the level required to add the skill
00702     vector<int32> skill_ids;
00703     uint32 level_required;
00704     char_script.OpenTable("skills");
00705     char_script.ReadTableKeys(skill_ids);
00706 
00707     // Only add the skills for which the experience level requirements are met
00708     for (uint32 i = 0; i < skill_ids.size(); i++) {
00709       level_required = char_script.ReadUInt(skill_ids[i]);
00710       if (level_required <= _experience_level) {
00711         AddSkill(static_cast<uint32>(skill_ids[i]));
00712       }
00713     }
00714 
00715     char_script.CloseTable();
00716 
00717     if (char_script.IsErrorDetected()) {
00718       if (GLOBAL_DEBUG) {
00719         cerr << "GLOBAL WARNING: GlobalCharacter constructor had errors in reading the character's "
00720           << "initial skill set. They are as follows:" << endl;
00721         cerr << char_script.GetErrorMessages() << endl;
00722       }
00723     }
00724   } // if (initial)
00725 
00726   char_script.CloseTable(); // "characters[id]"
00727   char_script.CloseTable(); // "characters"
00728 
00729   // (6): Determine the character's initial growth, if requested
00730   if (initial) {
00731     // Initialize the experience level milestones
00732     _growth._experience_for_last_level = _experience_points;
00733     _growth._experience_for_next_level = _experience_points;
00734     _growth._DetermineNextLevelExperience();
00735     try {
00736       ScriptCallFunction<void>(char_script.GetLuaState(), "DetermineGrowth", this);
00737       _growth._ConstructPeriodicGrowth();
00738     }
00739     catch (luabind::error e) {
00740       ScriptManager->HandleLuaError(e);
00741     }
00742     catch (luabind::cast_failed e) {
00743       ScriptManager->HandleCastError(e);
00744     }
00745   }
00746 
00747   if (char_script.IsErrorDetected()) {
00748     if (GLOBAL_DEBUG) {
00749       cerr << "GLOBAL WARNING: GlobalCharacter constructor had script read errors remaining when "
00750         << "it was finished with the file. They are as follows: " << endl;
00751       cerr << char_script.GetErrorMessages() << endl;
00752     }
00753   }
00754   
00755   char_script.CloseFile();
00756 
00757   // TEMP TEMP TEMP: Load the character's idle animation
00758   AnimatedImage idle;
00759   StillImage img;
00760   img.SetDimensions(64, 128);
00761   for (uint32 i = 0; i < 6; i ++) {
00762     idle.AddFrame(img, 10);
00763   }
00764   if (VideoManager->LoadAnimatedImageFromNumberElements(idle, "img/sprites/battle/characters/" + _filename + "_idle.png", 1, 6) == false) {
00765     exit(1);
00766   }
00767   idle.SetFrameIndex(0);
00768   _battle_animation["idle"] = idle;
00769 
00770   // Load the character's battle portraits from a multi image
00771   _battle_portraits.assign(5, StillImage());
00772   for (uint32 i = 0; i < _battle_portraits.size(); i++) {
00773     _battle_portraits[i].SetDimensions(100, 100);
00774   }
00775   if (VideoManager->LoadMultiImageFromNumberElements(_battle_portraits, "img/portraits/battle/" + _filename + "_damage.png", 1, 5) == false)
00776     exit(1);
00777 } // GlobalCharacter::GlobalCharacter(uint32 id, bool initial)
00778 
00779 
00780 
00781 GlobalCharacter::~GlobalCharacter() {
00782   // TODO: Remove all references to loaded image files
00783 }
00784 
00785 
00786 
00787 void GlobalCharacter::AddSkill(uint32 skill_id) {
00788   if (skill_id == 0) {
00789     if (GLOBAL_DEBUG)
00790       cerr << "GLOBAL WARNING: GlobalCharacter::AddSkill() failed because an invalid skill id was passed to it (0)" << endl;
00791     return;
00792   }
00793 
00794   if (_skills.find(skill_id) != _skills.end()) {
00795     if (GLOBAL_DEBUG)
00796       cerr << "GLOBAL WARNING: GlobalCharacter::AddSkill() failed because the character had already learned the skill "
00797         << "with the skill id value of: " << skill_id << endl;
00798   }
00799 
00800   GlobalSkill* skill = new GlobalSkill(skill_id);
00801   if (skill->GetID() == 0) { // Indicates that the skill failed to load successfully
00802     if (GLOBAL_DEBUG)
00803       cerr << "GLOBAL WARNING: GlobalCharacter::AddSkill() failed because the skill failed to load" << endl;
00804     delete skill;
00805     return;
00806   }
00807 
00808   // Insert the pointer to the new skill inside of the global skills map and the skill type vector
00809   _skills.insert(make_pair(skill_id, skill));
00810   switch (skill->GetType()) {
00811     case GLOBAL_SKILL_ATTACK:
00812       _attack_skills.push_back(skill);
00813       break;
00814     case GLOBAL_SKILL_DEFEND:
00815       _defense_skills.push_back(skill);
00816       break;
00817     case GLOBAL_SKILL_SUPPORT:
00818       _support_skills.push_back(skill);
00819       break;
00820     default:
00821       if (GLOBAL_DEBUG)
00822         cerr << "GLOBAL WARNING: GlobalCharacter::AddSkill() loaded a new skill with an unknown skill type: " << skill->GetType() << endl;
00823       break;
00824   }
00825 } // void GlobalCharacter::AddSkill(uint32 skill_id)
00826 
00827 
00828 
00829 bool GlobalCharacter::AddExperiencePoints(uint32 xp) {
00830   _experience_points += xp;
00831   _growth._CheckForGrowth();
00832   return _growth.IsGrowthDetected();
00833 }
00834 
00835 // -----------------------------------------------------------------------------
00836 // GlobalEnemy class
00837 // -----------------------------------------------------------------------------
00838 
00839 GlobalEnemy::GlobalEnemy(uint32 id) {
00840   _id = id;
00841   _experience_level = 1;
00842   _weapon_equipped = NULL;
00843   _armor_equipped.clear();
00844 
00845   // (1): Use the id member to determine the name of the data file that the enemy is defined in
00846   string file_ext;
00847   if (_id < 1) {
00848     cerr << "GLOBAL ERROR: invalid id for loading enemy data: " << _id << endl;
00849   } else if (_id < 101) {
00850     file_ext = "01";
00851   } else if (_id < 201) {
00852     file_ext = "02";
00853   }
00854   string filename = "dat/actors/enemies_set_" + file_ext + ".lua";
00855 
00856   // (2): Open the script file and table that store the enemy data
00857   ReadScriptDescriptor enemy_data;
00858   if (enemy_data.OpenFile(filename) == false) {
00859     cerr << "GLOBAL ERROR: failed to load enemy data file: " << _filename << endl;
00860     _id = 0;
00861     return;
00862   }
00863   enemy_data.OpenTable("enemies");
00864   enemy_data.OpenTable(_id);
00865 
00866   // (3): Load the enemy's name and sprite data
00867   _name = MakeUnicodeString(enemy_data.ReadString("name"));
00868   _filename = enemy_data.ReadString("filename");
00869   _sprite_width = enemy_data.ReadInt("sprite_width");
00870   _sprite_height = enemy_data.ReadInt("sprite_height");
00871 
00872   // (4): Attempt to load the MultiImage for the sprite's frames, which should contain one row and four columns of images
00873   _battle_sprite_frames.assign(4, StillImage());
00874   string sprite_filename = "img/sprites/battle/enemies/" + _filename + ".png";
00875   if (VideoManager->LoadMultiImageFromNumberElements(_battle_sprite_frames, sprite_filename, 1, 4) == false) {
00876     cerr << "GLOBAL WARNING: failed to load sprite frames for enemy: " << sprite_filename << endl;
00877   }
00878 
00879   // (5): Load the enemy's initial stats
00880   enemy_data.OpenTable("initial_stats");
00881   _max_hit_points = enemy_data.ReadUInt("hit_points");
00882   _hit_points = _max_hit_points;
00883   _max_skill_points = enemy_data.ReadUInt("skill_points");
00884   _skill_points = _max_skill_points;
00885   _experience_points = enemy_data.ReadUInt("experience_points");
00886   _strength = enemy_data.ReadUInt("strength");
00887   _vigor = enemy_data.ReadUInt("vigor");
00888   _fortitude = enemy_data.ReadUInt("fortitude");
00889   _protection = enemy_data.ReadUInt("protection");
00890   _agility = enemy_data.ReadUInt("agility");
00891   _evade = enemy_data.ReadFloat("evade");
00892   _drunes_dropped = enemy_data.ReadUInt("drunes");
00893   enemy_data.CloseTable();
00894 
00895   // (6): Load the enemy's growth statistics
00896   enemy_data.OpenTable("growth_stats");
00897   _growth_hit_points = enemy_data.ReadFloat("hit_points");
00898   _growth_skill_points = enemy_data.ReadFloat("skill_points");
00899   _growth_experience_points = enemy_data.ReadFloat("experience_points");
00900   _growth_strength = enemy_data.ReadFloat("strength");
00901   _growth_vigor = enemy_data.ReadFloat("vigor");
00902   _growth_fortitude = enemy_data.ReadFloat("fortitude");
00903   _growth_protection = enemy_data.ReadFloat("protection");
00904   _growth_agility = enemy_data.ReadFloat("agility");
00905   _growth_evade = enemy_data.ReadFloat("evade");
00906   _growth_drunes = enemy_data.ReadFloat("drunes");
00907   enemy_data.CloseTable();
00908 
00909   // (7): Create the attack points for the enemy
00910   enemy_data.OpenTable("attack_points");
00911   uint32 ap_size = enemy_data.GetTableSize();
00912   for (uint32 i = 1; i <= ap_size; i++) {
00913     _attack_points.push_back(new GlobalAttackPoint(this));
00914     enemy_data.OpenTable(i);
00915     if (_attack_points.back()->_LoadData(enemy_data) == false) {
00916       cerr << "GLOBAL ERROR: GlobalEnemy constructor was unable to load data for an attack point" << endl;
00917       exit(1);
00918     }
00919     enemy_data.CloseTable();
00920   }
00921   enemy_data.CloseTable();
00922 
00923   // (8): Add the set of skills to the enemy
00924   vector<int32> skill_ids;
00925   enemy_data.OpenTable("skills");
00926   enemy_data.ReadTableKeys(skill_ids);
00927   for (uint32 i = 0; i < skill_ids.size(); i++) {
00928     uint32 skill = static_cast<uint32>(skill_ids[i]);
00929     if (_skill_set.find(skill) == _skill_set.end()) {
00930       _skill_set.insert(make_pair(skill, enemy_data.ReadUInt(skill)));
00931     }
00932     else {
00933       if (GLOBAL_DEBUG)
00934         cerr << "GLOBAL WARNING: GlobalEnemy constructor tried to add a skill to the "
00935           << "skill set multiple times" << endl;
00936     }
00937   }
00938 
00939   // (8): Load the possible items that the enemy may drop
00940   enemy_data.OpenTable("drop_objects");
00941   for (uint32 i = 1; i <= enemy_data.GetTableSize(); i++) {
00942     enemy_data.OpenTable(i);
00943     _dropped_objects.push_back(enemy_data.ReadUInt(1));
00944     _dropped_chance.push_back(enemy_data.ReadFloat(2));
00945     _dropped_level_required.push_back(enemy_data.ReadUInt(3));
00946     enemy_data.CloseTable();
00947   }
00948   enemy_data.CloseTable();
00949 
00950   enemy_data.CloseTable(); // enemies[_id]
00951   enemy_data.CloseTable(); // enemies
00952 
00953   if (enemy_data.IsErrorDetected()) {
00954     if (GLOBAL_DEBUG) {
00955       cerr << "GLOBAL WARNING: GlobalEnemy constructor had script read errors remaining when "
00956         << "it was finished with the file. They are as follows: " << endl;
00957       cerr << enemy_data.GetErrorMessages() << endl;
00958     }
00959   }
00960 
00961   enemy_data.CloseFile();
00962 } // GlobalEnemy::~GlobalEnemy()
00963 
00964 
00965 
00966 GlobalEnemy::~GlobalEnemy() {
00967   // TODO: dereference all loaded image files
00968 }
00969 
00970 
00971 
00972 void GlobalEnemy::AddSkill(uint32 skill_id) {
00973   if (skill_id == 0) {
00974     if (GLOBAL_DEBUG)
00975       cerr << "GLOBAL WARNING: GlobalEnemy::AddSkill() failed because an invalid skill id was passed to it (0)" << endl;
00976     return;
00977   }
00978 
00979   if (_skills.find(skill_id) != _skills.end()) {
00980     if (GLOBAL_DEBUG)
00981       cerr << "GLOBAL WARNING: GlobalEnemy::AddSkill() failed because the enemy had already learned the skill "
00982         << "with the skill id value of: " << skill_id << endl;
00983   }
00984 
00985   GlobalSkill* skill = new GlobalSkill(skill_id);
00986   if (skill->GetID() == 0) { // Indicates that the skill failed to load successfully
00987     if (GLOBAL_DEBUG)
00988       cerr << "GLOBAL WARNING: GlobalCharacter::AddSkill() failed because the skill failed to load" << endl;
00989     delete skill;
00990     return;
00991   }
00992 
00993   // Insert the pointer to the new skill inside of the global skills map and the skill type vector
00994   _skills.insert(make_pair(skill_id, skill));
00995 }
00996 
00997 
00998 
00999 void GlobalEnemy::Initialize(uint32 xp_level) {
01000   if (xp_level == 0) {
01001     if (GLOBAL_DEBUG)
01002       cerr << "GLOBAL WARNING: GlobalEnemy::Initialize() was called with an xp_level argument of 0" << endl;
01003     return;
01004   }
01005 
01006   if (_skills.empty() == false) { // Indicates that the enemy has already been initialized
01007     if (GLOBAL_DEBUG)
01008       cerr << "GLOBAL WARNING: GlobalEnemy::Initialize() was invoked for an already initialized enemy" << endl;
01009     return;
01010   }
01011 
01012   _experience_level = xp_level;
01013 
01014   // ----- (1): Add all new skills that should be available at the current experience level
01015   for (map<uint32, uint32>::iterator i = _skill_set.begin(); i != _skill_set.end(); i++) {
01016     if (_experience_level >= i->second)
01017       AddSkill(i->first);
01018   }
01019 
01020   if (_skills.empty()) {
01021     if (GLOBAL_DEBUG)
01022       cerr << "GLOBAL WARNING: GlobalEnemy::Initialize() did not add any skills for the enemy" << endl;
01023   }
01024 
01025   // ----- (2): Add the new stats to the growth rate multiplied by the experience level
01026   _max_hit_points    += static_cast<uint32>(_growth_hit_points * _experience_level);
01027   _max_skill_points  += static_cast<uint32>(_growth_skill_points * _experience_level);
01028   _experience_points += static_cast<uint32>(_growth_experience_points * _experience_level);
01029   _strength          += static_cast<uint32>(_growth_strength * _experience_level);
01030   _vigor             += static_cast<uint32>(_growth_vigor * _experience_level);
01031   _fortitude         += static_cast<uint32>(_growth_fortitude * _experience_level);
01032   _protection        += static_cast<uint32>(_growth_protection * _experience_level);
01033   _agility           += static_cast<uint32>(_growth_agility * _experience_level);
01034   _evade             += static_cast<float>(_growth_evade * _experience_level);
01035   _drunes_dropped    += static_cast<uint32>(_growth_drunes * _experience_level);
01036 
01037   // ----- (3): Randomize the new stats by using a guassian random variable
01038   // Use the inital stats as the means and a standard deviation of 10% of the mean
01039   _max_hit_points     = GaussianRandomValue(_max_hit_points, _max_hit_points / 10.0f);
01040   _max_skill_points   = GaussianRandomValue(_max_skill_points, _max_skill_points / 10.0f);
01041   _experience_points  = GaussianRandomValue(_experience_points, _experience_points / 10.0f);
01042   _strength           = GaussianRandomValue(_strength, _strength / 10.0f);
01043   _vigor              = GaussianRandomValue(_strength, _strength / 10.0f);
01044   _fortitude          = GaussianRandomValue(_fortitude, _fortitude / 10.0f);
01045   _protection         = GaussianRandomValue(_protection, _protection / 10.0f);
01046   _agility            = GaussianRandomValue(_agility, _agility / 10.0f);
01047   // TODO: need a gaussian random var function that takes a float arg
01048   //_evade              = static_cast<float>(GaussianRandomValue(_evade, _evade / 10.0f));
01049   _drunes_dropped     = GaussianRandomValue(_drunes_dropped, _drunes_dropped / 10.0f);
01050 
01051   // ----- (4): Set the current hit points and skill points to their new maximum values
01052   _hit_points = _max_hit_points;
01053   _skill_points = _max_skill_points;
01054 } // void GlobalEnemy::Initialize(uint32 xp_level)
01055 
01056 
01057 
01058 void GlobalEnemy::DetermineDroppedObjects(vector<GlobalObject*>& objects) {
01059   objects.clear();
01060 
01061   for (uint32 i = 0; i < _dropped_objects.size(); i++) {
01062     if (_experience_level >= _dropped_level_required[i]) {
01063       if (_dropped_chance[i] < RandomFloat()) {
01064         objects.push_back(GlobalCreateNewObject(_dropped_objects[i]));
01065       }
01066     }
01067   }
01068 }
01069 
01070 // -----------------------------------------------------------------------------
01071 // GlobalParty class
01072 // -----------------------------------------------------------------------------
01073 
01074 void GlobalParty::AddActor(GlobalActor* actor, int32 index) {
01075   if (actor == NULL) {
01076     if (GLOBAL_DEBUG)
01077       cerr << "GLOBAL WARNING: GlobalParty::AddActor() was passed a NULL actor argument" << endl;
01078     return;
01079   }
01080 
01081   if (_allow_duplicates == false) {
01082     // Check that this actor is not already in the party
01083     for (uint32 i = 0; i < _actors.size(); i++) {
01084       if (actor->GetID() == _actors[i]->GetID()) {
01085         if (GLOBAL_DEBUG)
01086           cerr << "GLOBAL WARNING: GlobalParty::AddActor() attempted to add a duplicate actor "
01087             << "when duplicates were not allowed: " << actor->GetID() << endl;
01088         return;
01089       }
01090     }
01091   }
01092 
01093   if (index < 0) {
01094     _actors.push_back(actor);
01095   }
01096   else if (static_cast<uint32>(index) >= _actors.size()) {
01097     if (GLOBAL_DEBUG)
01098       cerr << "GLOBAL WARNING: GlobalParty::AddActor() was given an index argument that exceeded "
01099         << "the current party size: " << index << endl;
01100     return;
01101   }
01102   else {
01103     vector<GlobalActor*>::iterator position = _actors.begin();
01104     for (int32 i = 0; i < index; i++, position++);
01105     _actors.insert(position, actor);
01106   }
01107 } // void GlobalParty::AddActor(GlobalActor* actor, int32 index)
01108 
01109 
01110 
01111 GlobalActor* GlobalParty::RemoveActorAtIndex(uint32 index) {
01112   if (index >= _actors.size()) {
01113     if (GLOBAL_DEBUG)
01114       cerr << "GLOBAL WARNING: GlobalParty::RemoveActorAtIndex() was called with an out-of-bounds "
01115         << "index argument: " << index << endl;
01116     return NULL;
01117   }
01118 
01119   GlobalActor* removed_actor = _actors[index];
01120   vector<GlobalActor*>::iterator position = _actors.begin();
01121   for (uint32 i = 0; i < index; i++, position++);
01122   _actors.erase(position);
01123 
01124   return removed_actor;
01125 } // GlobalActor* GlobalParty::RemoveActorAtIndex(uint32 index)
01126 
01127 
01128 
01129 GlobalActor* GlobalParty::RemoveActorByID(uint32 id) {
01130   if (_allow_duplicates) {
01131     if (GLOBAL_DEBUG)
01132       cerr << "GLOBAL WARNING: GlobalParty::RemoveActorByID() was called when duplicate actors "
01133         << "were allowed in the party: " << id << endl;
01134     return NULL;
01135   }
01136 
01137   GlobalActor* removed_actor = NULL;
01138   for (vector<GlobalActor*>::iterator position = _actors.begin(); position != _actors.end(); position++) {
01139     if (id == (*position)->GetID()) {
01140       removed_actor = *position;
01141       _actors.erase(position);
01142       break;
01143     }
01144   }
01145 
01146   if (removed_actor == NULL) {
01147     if (GLOBAL_DEBUG)
01148       cerr << "GLOBAL WARNING: GlobalParty::RemoveActorByID() failed to find an actor in the party "
01149         << "with the requested id: " << id << endl;
01150   }
01151 
01152   return removed_actor;
01153 } // GlobalActor* GlobalParty::RemoveActorByID(uint32 id)
01154 
01155 
01156 
01157 void GlobalParty::SwapActorsByIndex(uint32 first_index, uint32 second_index) {
01158   if (first_index == second_index) {
01159     if (GLOBAL_DEBUG)
01160       cerr << "GLOBAL WARNING: GlobalParty::SwapActorsByIndex() was called with both the first and "
01161         << "second index arguments equal to one another: " << first_index << endl;
01162     return;
01163   }
01164 
01165   if (first_index >= _actors.size()) {
01166     if (GLOBAL_DEBUG)
01167       cerr << "GLOBAL WARNING: GlobalParty::SwapActorsByIndex() was called with an out-of-bounds "
01168         << "first index argument: " << first_index << endl;
01169     return;
01170   }
01171 
01172   if (second_index >= _actors.size()) {
01173     if (GLOBAL_DEBUG)
01174       cerr << "GLOBAL WARNING: GlobalParty::SwapActorsByIndex() was called with an out-of-bounds "
01175         << "second index argument: " << second_index << endl;
01176     return;
01177   }
01178 
01179   GlobalActor* tmp = _actors[first_index];
01180   _actors[first_index] = _actors[second_index];
01181   _actors[second_index] = tmp;
01182 } // void GlobalParty::SwapActorsByIndex(uint32 first_index, uint32 second_index)
01183 
01184 
01185 
01186 void GlobalParty::SwapActorsByID(uint32 first_id, uint32 second_id) {
01187   if (first_id == second_id) {
01188     if (GLOBAL_DEBUG)
01189       cerr << "GLOBAL WARNING: GlobalParty::SwapActorsByID() was called with both the first and "
01190         << "second id arguments equal to one another: " << first_id << endl;
01191     return;
01192   }
01193 
01194   if (_allow_duplicates) {
01195     if (GLOBAL_DEBUG)
01196       cerr << "GLOBAL WARNING: GlobalParty::SwapActorsByID() was called when duplicate actors "
01197         << "were allowed in the party" << endl;
01198     return;
01199   }
01200 
01201   vector<GlobalActor*>::iterator first_position;
01202   vector<GlobalActor*>::iterator second_position;
01203   for (first_position = _actors.begin(); first_position != _actors.end(); first_position++) {
01204     if ((*first_position)->GetID() == first_id)
01205       break;
01206   }
01207   for (second_position = _actors.begin(); second_position != _actors.end(); second_position++) {
01208     if ((*second_position)->GetID() == second_id)
01209       break;
01210   }
01211 
01212   if (first_position == _actors.end()) {
01213     if (GLOBAL_DEBUG)
01214       cerr << "GLOBAL WARNING: GlobalParty::SwapActorsByID() failed because there did not exist "
01215         << "an actor with an id equal to the first_id argument: " << first_id << endl;
01216     return;
01217   }
01218   if (second_position == _actors.end()) {
01219     if (GLOBAL_DEBUG)
01220       cerr << "GLOBAL WARNING: GlobalParty::SwapActorsByID() failed because there did not exist "
01221         << "an actor with an id equal to the second_id argument: " << second_id << endl;
01222     return;
01223   }
01224 
01225   GlobalActor* tmp = *first_position;
01226   *first_position = *second_position;
01227   *second_position = tmp;
01228 } // void GlobalParty::SwapActorsByID(uint32 first_id, uint32 second_id)
01229 
01230 
01231 
01232 GlobalActor* GlobalParty::ReplaceActorByIndex(uint32 index, GlobalActor* new_actor) {
01233   if (new_actor == NULL) {
01234     if (GLOBAL_DEBUG)
01235       cerr << "GLOBAL WARNING: GlobalParty::ReplaceActorByIndex() was passed a NULL actor argument" << endl;
01236     return NULL;
01237   }
01238 
01239   if (index >= _actors.size()) {
01240     if (GLOBAL_DEBUG)
01241       cerr << "GLOBAL WARNING: GlobalParty::ReplaceActorByIndex() was called with an out-of-bounds "
01242         << "index argument: " << index << endl;
01243     return NULL;
01244   }
01245 
01246   GlobalActor* tmp = _actors[index];
01247   _actors[index] = new_actor;
01248   return tmp;
01249 } // GlobalActor* GlobalParty::ReplaceActorByIndex(uint32 index, GlobalActor* new_actor)
01250 
01251 
01252 
01253 GlobalActor* GlobalParty::ReplaceActorByID(uint32 id, GlobalActor* new_actor) {
01254   if (_allow_duplicates) {
01255     if (GLOBAL_DEBUG)
01256       cerr << "GLOBAL WARNING: GlobalParty::ReplaceActorByID() was called when duplicate actors "
01257         << "were allowed in the party: " << id << endl;
01258     return NULL;
01259   }
01260 
01261   if (new_actor == NULL) {
01262     if (GLOBAL_DEBUG)
01263       cerr << "GLOBAL WARNING: GlobalParty::ReplaceActorByID() was passed a NULL actor argument" << endl;
01264     return NULL;
01265   }
01266 
01267   GlobalActor* removed_actor = NULL;
01268   for (vector<GlobalActor*>::iterator position = _actors.begin(); position != _actors.end(); position++) {
01269     if (id == (*position)->GetID()) {
01270       removed_actor = *position;
01271       *position = new_actor;
01272       break;
01273     }
01274   }
01275 
01276   if (removed_actor == NULL) {
01277     if (GLOBAL_DEBUG)
01278       cerr << "GLOBAL WARNING: GlobalParty::ReplaceActorByID() failed to find an actor in the party "
01279         << "with the requested id: " << id << endl;
01280   }
01281 
01282   return removed_actor;
01283 } // GlobalActor* GlobalParty::ReplaceActorByID(uint32 id, GlobalActor* new_actor)
01284 
01285 
01286 
01287 float GlobalParty::AverageExperienceLevel() const {
01288   if (_actors.empty())
01289     return 0.0f;
01290 
01291   float xp_level_sum = 0.0f;
01292   for (uint32 i = 0; i < _actors.size(); i++)
01293     xp_level_sum += static_cast<float>(_actors[i]->GetExperienceLevel());
01294   return (xp_level_sum / static_cast<float>(_actors.size()));
01295 } // float GlobalParty::AverageExperienceLevel()
01296 
01297 
01298 
01299 GlobalActor* GlobalParty::GetActorByID(uint32 id) const {
01300   if (_allow_duplicates) {
01301     if (GLOBAL_DEBUG)
01302       cerr << "GLOBAL WARNING: GlobalParty::GetActorByID() was called when duplicate actors "
01303         << "were allowed in the party: " << id << endl;
01304     return NULL;
01305   }
01306 
01307   for (uint32 i = 0; i < _actors.size(); i++) {
01308     if (_actors[i]->GetID() == id) {
01309       return _actors[i];
01310     }
01311   }
01312 
01313   if (GLOBAL_DEBUG)
01314     cerr << "GLOBAL WARNING: GlobalParty::GetActorByID() failed to find an actor in the party "
01315         << "with the requested id: " << id << endl;
01316   return NULL;
01317 } // float GlobalParty::AverageExperienceLevel()
01318 
01319 } // namespace hoa_global

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