00001
00002
00003
00004
00005
00006
00007
00009
00016 #include "utils.h"
00017 #include "map.h"
00018 #include "map_objects.h"
00019 #include "map_sprites.h"
00020 #include "map_dialogue.h"
00021 #include "map_zones.h"
00022 #include "audio.h"
00023 #include "video.h"
00024 #include "global.h"
00025 #include "script.h"
00026 #include "input.h"
00027 #include "system.h"
00028 #include "battle.h"
00029 #include "menu.h"
00030
00031 using namespace std;
00032 using namespace hoa_map::private_map;
00033 using namespace hoa_utils;
00034 using namespace hoa_audio;
00035 using namespace hoa_video;
00036 using namespace hoa_mode_manager;
00037 using namespace hoa_input;
00038 using namespace hoa_system;
00039 using namespace hoa_input;
00040 using namespace hoa_global;
00041 using namespace hoa_script;
00042 using namespace hoa_battle;
00043 using namespace hoa_menu;
00044
00045 namespace hoa_map {
00046
00047 bool MAP_DEBUG = false;
00048
00049 MapMode *MapMode::_current_map = NULL;
00050 MapMode *MapMode::_loading_map = NULL;
00051 bool MapMode::_show_dialogue_icons = true;
00052
00053
00054
00055
00056
00057
00058
00059 MapMode::MapMode(string filename) :
00060 _map_filename(filename)
00061 {
00062 if (MAP_DEBUG)
00063 cout << "MAP: MapMode constructor invoked" << endl;
00064 _loading_map = this;
00065
00066 mode_type = MODE_MANAGER_MAP_MODE;
00067 _map_state = EXPLORE;
00068 _lastID = 1000;
00069
00070 _virtual_focus = new VirtualSprite();
00071 _virtual_focus->SetXPosition(0, 0.0f);
00072 _virtual_focus->SetYPosition(0, 0.0f);
00073 _virtual_focus->movement_speed = NORMAL_SPEED;
00074 _virtual_focus->SetNoCollision(true);
00075 _virtual_focus->SetVisible(false);
00076
00077 _dialogue_manager = new DialogueManager();
00078
00079 _intro_timer.Initialize(7000, 0, this);
00080
00081
00082 _Load();
00083
00084
00085 if (private_map::new_dialogue_icon.GetNumFrames() == 0) {
00086 std::vector<StillImage> frames;
00087 VideoManager->LoadMultiImageFromElementsSize(frames, "img/misc/dialogue_icon.png", 32, 32);
00088
00089 for( size_t i = 0; i < frames.size(); ++i ) {
00090 private_map::new_dialogue_icon.AddFrame(frames[i], 100);
00091 }
00092
00093 private_map::new_dialogue_icon.SetDimensions(2, 2);
00094 private_map::new_dialogue_icon.Load();
00095 }
00096 }
00097
00098
00099
00100 MapMode::~MapMode() {
00101 if (MAP_DEBUG) cout << "MAP: MapMode destructor invoked" << endl;
00102
00103 for (uint32 i = 0; i < _music.size(); i++) {
00104 _music[i].FreeMusic();
00105 }
00106
00107 for (uint32 i = 0; i < _sounds.size(); i++) {
00108 _sounds[i].FreeSound();
00109 }
00110
00111
00112 for (uint32 i = 0; i < _tile_images.size(); i++) {
00113 delete(_tile_images[i]);
00114 }
00115
00116
00117 for (uint32 i = 0; i < _ground_objects.size(); i++) {
00118 delete(_ground_objects[i]);
00119 }
00120
00121 for (uint32 i = 0; i < _pass_objects.size(); i++) {
00122 delete(_pass_objects[i]);
00123 }
00124 for (uint32 i = 0; i < _sky_objects.size(); i++) {
00125 delete(_sky_objects[i]);
00126 }
00127 delete(_virtual_focus);
00128
00129 delete(_dialogue_manager);
00130
00131 _map_script.CloseFile();
00132 }
00133
00134
00135
00136 void MapMode::Reset() {
00137
00138 VideoManager->SetCoordSys(0.0f, SCREEN_COLS, SCREEN_ROWS, 0.0f);
00139 VideoManager->SetDrawFlags(VIDEO_X_CENTER, VIDEO_Y_BOTTOM, 0);
00140
00141 if (!VideoManager->SetFont("map"))
00142 cerr << "MAP ERROR: Failed to set the map font" << endl;
00143
00144
00145 MapMode::_current_map = this;
00146
00147
00148 if (_music.size() > 0 && _music[0].IsPlaying() == false) {
00149 _music[0].PlayMusic();
00150 }
00151
00152 _intro_timer.Run();
00153 }
00154
00155
00156
00157 void MapMode::_Load() {
00158
00159 if (_map_script.OpenFile(_map_filename) == false) {
00160 return;
00161 }
00162
00163 _map_name = MakeUnicodeString(_map_script.ReadString("map_name"));
00164 _location_graphic.SetFilename("img/menus/locations/" + _map_script.ReadString("location_filename"));
00165 if (_location_graphic.Load() == false) {
00166 cerr << "MAP ERROR: failed to load location graphic image: " << _location_graphic.GetFilename() << endl;
00167 }
00168
00169 _num_tile_rows = _map_script.ReadInt("num_tile_rows");
00170 _num_tile_cols = _map_script.ReadInt("num_tile_cols");
00171 _num_grid_rows = _num_tile_rows * 2;
00172 _num_grid_cols = _num_tile_cols * 2;
00173
00174
00175
00176
00177 if (_map_script.GetTableSize("map_grid") + 1 != _num_grid_rows) {
00178 cerr << "MAP ERROR: In MapMode::_Load(), the map_grid table had an incorrect number of rows" << endl;
00179 return;
00180 }
00181 if (_map_script.GetTableSize("lower_layer") + 1 != _num_tile_rows) {
00182 cerr << "MAP ERROR: In MapMode::_Load(), the lower_layer table had an incorrect number of rows" << endl;
00183 return;
00184 }
00185 if (_map_script.GetTableSize("middle_layer") + 1 != _num_tile_rows) {
00186 cerr << "MAP ERROR: In MapMode::_Load(), the middle_layer table had an incorrect number of rows" << endl;
00187 return;
00188 }
00189 if (_map_script.GetTableSize("upper_layer") + 1 != _num_tile_rows) {
00190 cerr << "MAP ERROR: In MapMode::_Load(), the upper_layer table had an incorrect number of rows" << endl;
00191 return;
00192 }
00193
00194
00195 _LoadTiles();
00196
00197
00198 vector<string> sound_filenames;
00199 _map_script.ReadStringVector("sound_filenames", sound_filenames);
00200
00201 for (uint32 i = 0; i < sound_filenames.size(); i++) {
00202 SoundDescriptor new_sound;
00203 if (new_sound.LoadSound(sound_filenames[i]) == true) {
00204 _sounds.push_back(new_sound);
00205 }
00206 else {
00207 cerr << "MAP ERROR: failed to load map sound: " << sound_filenames[i] << endl;
00208 return;
00209 }
00210 }
00211
00212 vector<string> music_filenames;
00213 _map_script.ReadStringVector("music_filenames", music_filenames);
00214 for (uint32 i = 0; i < music_filenames.size(); i++) {
00215 MusicDescriptor new_music;
00216 if (new_music.LoadMusic(music_filenames[i]) == true) {
00217 _music.push_back(new_music);
00218 }
00219 else {
00220 cerr << "MAP ERROR: failed to load map music: " << music_filenames[i] << endl;
00221 return;
00222 }
00223 }
00224
00225
00226 vector<int32> enemy_ids;
00227 _map_script.ReadIntVector("enemy_ids", enemy_ids);
00228 for (uint32 i = 0; i < enemy_ids.size(); i++) {
00229 _enemies.push_back(GlobalEnemy(enemy_ids[i]));
00230 }
00231
00232
00233 ScriptCallFunction<void>(_map_script.GetLuaState(), "Load", this);
00234 _update_function = _map_script.ReadFunctionPointer("Update");
00235 }
00236
00237
00238
00239 void MapMode::_LoadTiles() {
00240
00241 vector<string> tileset_filenames;
00242
00243 vector<vector<StillImage> > tileset_images;
00244
00245 vector<int32> tile_references;
00246
00247 map<uint32, AnimatedImage> tile_animations;
00248
00249
00250
00251 _map_script.OpenTable("map_grid");
00252 for (uint16 r = 0; r < _num_grid_rows; r++) {
00253 _map_grid.push_back(vector<uint32>());
00254 _map_script.ReadUIntVector(r, _map_grid.back());
00255 }
00256 _map_script.CloseTable();
00257
00258
00259 _map_script.ReadStringVector("tileset_filenames", tileset_filenames);
00260
00261
00262 for (uint32 i = 0; i < tileset_filenames.size(); i++) {
00263
00264 string image_filename = "img/tilesets/" + tileset_filenames[i] + ".png";
00265 tileset_images.push_back(vector<StillImage>(TILES_PER_TILESET));
00266
00267 for (uint32 j = 0; j < TILES_PER_TILESET; j++) {
00268 tileset_images[i][j].SetDimensions(2.0f, 2.0f);
00269 }
00270
00271 if (VideoManager->LoadMultiImageFromNumberElements(tileset_images[i], image_filename, 16, 16) == false) {
00272 cerr << "MAP ERROR: MapMode::_LoadTiles() failed to load tileset image:" << image_filename << endl;
00273 return;
00274 }
00275 }
00276
00277
00278
00279 for (uint32 r = 0; r < _num_tile_rows; r++) {
00280 _tile_grid.push_back(vector<MapTile>(_num_tile_cols));
00281 }
00282
00283 vector<int32> table_row;
00284
00285
00286 _map_script.OpenTable("lower_layer");
00287 for (uint32 r = 0; r < _num_tile_rows; r++) {
00288 table_row.clear();
00289 _map_script.ReadIntVector(r, table_row);
00290 for (uint32 c = 0; c < _num_tile_cols; c++) {
00291 _tile_grid[r][c].lower_layer = table_row[c];
00292 }
00293 }
00294 _map_script.CloseTable();
00295
00296
00297 _map_script.OpenTable("middle_layer");
00298 for (uint32 r = 0; r < _num_tile_rows; r++) {
00299 table_row.clear();
00300 _map_script.ReadIntVector(r, table_row);
00301 for (uint32 c = 0; c < _num_tile_cols; c++) {
00302 _tile_grid[r][c].middle_layer = table_row[c];
00303 }
00304 }
00305 _map_script.CloseTable();
00306
00307
00308 _map_script.OpenTable("upper_layer");
00309 for (uint32 r = 0; r < _num_tile_rows; r++) {
00310 table_row.clear();
00311 _map_script.ReadIntVector(r, table_row);
00312 for (uint32 c = 0; c < _num_tile_cols; c++) {
00313 _tile_grid[r][c].upper_layer = table_row[c];
00314 }
00315 }
00316 _map_script.CloseTable();
00317
00318
00319
00320
00321 tile_references.assign(tileset_filenames.size() * TILES_PER_TILESET, -1);
00322
00323 for (uint32 r = 0; r < _num_tile_rows; r++) {
00324 for (uint32 c = 0; c < _num_tile_cols; c++) {
00325 if (_tile_grid[r][c].lower_layer >= 0)
00326 tile_references[_tile_grid[r][c].lower_layer] = 0;
00327 if (_tile_grid[r][c].middle_layer >= 0)
00328 tile_references[_tile_grid[r][c].middle_layer] = 0;
00329 if (_tile_grid[r][c].upper_layer >= 0)
00330 tile_references[_tile_grid[r][c].upper_layer] = 0;
00331 }
00332 }
00333
00334
00335
00336
00337
00338
00339 uint32 next_index = 0;
00340
00341 for (uint32 i = 0; i < tile_references.size(); i++) {
00342 if (tile_references[i] >= 0) {
00343 tile_references[i] = next_index;
00344 next_index++;
00345 }
00346 }
00347
00348
00349 for (uint32 r = 0; r < _num_tile_rows; r++) {
00350 for (uint32 c = 0; c < _num_tile_cols; c++) {
00351 if (_tile_grid[r][c].lower_layer >= 0)
00352 _tile_grid[r][c].lower_layer = tile_references[_tile_grid[r][c].lower_layer];
00353 if (_tile_grid[r][c].middle_layer >= 0)
00354 _tile_grid[r][c].middle_layer = tile_references[_tile_grid[r][c].middle_layer];
00355 if (_tile_grid[r][c].upper_layer >= 0)
00356 _tile_grid[r][c].upper_layer = tile_references[_tile_grid[r][c].upper_layer];
00357 }
00358 }
00359
00360
00361
00362 ReadScriptDescriptor tileset_script;
00363 vector<uint32> animation_info;
00364
00365 for (uint32 i = 0; i < tileset_filenames.size(); i++) {
00366 if (tileset_script.OpenFile("dat/tilesets/" + tileset_filenames[i] + ".lua") == false) {
00367 cerr << "MAP ERROR: In MapMode::_LoadTiles(), the map failed to load because it could not open a tileset definition file: "
00368 << tileset_script.GetFilename() << endl;
00369 return;
00370 }
00371
00372 tileset_script.OpenTable("animated_tiles");
00373 for (uint32 j = 1; j <= tileset_script.GetTableSize(); j++) {
00374 animation_info.clear();
00375 tileset_script.ReadUIntVector(j, animation_info);
00376
00377
00378 uint32 first_frame_index = animation_info[0] + (i * TILES_PER_TILESET);
00379
00380
00381 if (tile_references[first_frame_index] == -1) {
00382 continue;
00383 }
00384
00385 AnimatedImage new_animation;
00386 new_animation.SetDimensions(2.0f, 2.0f);
00387
00388
00389 for (uint32 k = 0; k < animation_info.size(); k += 2) {
00390 new_animation.AddFrame(tileset_images[i][animation_info[k]], animation_info[k+1]);
00391 }
00392
00393 tile_animations.insert(make_pair(first_frame_index, new_animation));
00394 }
00395 tileset_script.CloseTable();
00396 tileset_script.CloseFile();
00397 }
00398
00399
00400
00401 for (uint32 i = 0; i < tileset_images.size(); i++) {
00402 for (uint32 j = 0; j < TILES_PER_TILESET; j++) {
00403 uint32 reference = (i * TILES_PER_TILESET) + j;
00404
00405 if (tile_references[reference] >= 0) {
00406
00407 if (tile_animations.find(reference) == tile_animations.end()) {
00408 _tile_images.push_back(new StillImage(tileset_images[i][j]));
00409 }
00410
00411
00412 else {
00413 AnimatedImage* new_animated_tile = new AnimatedImage(tile_animations[reference]);
00414 _tile_images.push_back(new_animated_tile);
00415 _animated_tile_images.push_back(new_animated_tile);
00416 }
00417 }
00418 }
00419 }
00420
00421
00422 tileset_images.clear();
00423 }
00424
00425
00426
00427
00428
00429
00430 void MapMode::Update() {
00431 _time_elapsed = SystemManager->GetUpdateTime();
00432
00433
00434 ScriptCallFunction<void>(_update_function);
00435
00436
00437 switch (_map_state) {
00438 case EXPLORE:
00439 _HandleInputExplore();
00440 break;
00441 case DIALOGUE:
00442 _dialogue_manager->Update();
00443 break;
00444 default:
00445 _HandleInputExplore();
00446 break;
00447 }
00448
00449
00450 for (uint32 i = 0; i < _animated_tile_images.size(); i++) {
00451 _animated_tile_images[i]->Update();
00452 }
00453
00454
00455 for( uint32 i = 0; i < _zones.size(); i++ ) {
00456 _zones[i]->Update();
00457 }
00458
00459 for (uint32 i = 0; i < _ground_objects.size(); i++) {
00460 _ground_objects[i]->Update();
00461 }
00462 for (uint32 i = 0; i < _pass_objects.size(); i++) {
00463 _pass_objects[i]->Update();
00464 }
00465 for (uint32 i = 0; i < _sky_objects.size(); i++) {
00466 _sky_objects[i]->Update();
00467 }
00468
00469
00470 std::sort( _ground_objects.begin(), _ground_objects.end(), MapObject_Ptr_Less() );
00471 }
00472
00473
00474
00475 void MapMode::_HandleInputExplore() {
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 if (InputManager->MenuPress()) {
00492 MenuMode *MM = new MenuMode(_map_name, _location_graphic.GetFilename());
00493 ModeManager->Push(MM);
00494 return;
00495 }
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 if (InputManager->ConfirmPress()) {
00510 MapObject* obj = _FindNearestObject(_camera);
00511 if (obj && (obj->GetType() == VIRTUAL_TYPE || obj->GetType() == SPRITE_TYPE)) {
00512 VirtualSprite *sp = reinterpret_cast<VirtualSprite*>(obj);
00513
00514 if (sp->HasDialogue()) {
00515 sp->SaveState();
00516 _camera->moving = false;
00517
00518 sp->moving = false;
00519 sp->current_action = -1;
00520 sp->SetDirection(VirtualSprite::CalculateOppositeDirection(_camera->GetDirection()));
00521 _dialogue_manager->SetCurrentDialogue(sp->GetCurrentDialogue());
00522 sp->NextDialogue();
00523 _map_state = DIALOGUE;
00524 return;
00525 }
00526 }
00527 }
00528
00529
00530 if (InputManager->UpState() || InputManager->DownState() || InputManager->LeftState() || InputManager->RightState()) {
00531 _camera->moving = true;
00532 }
00533 else {
00534 _camera->moving = false;
00535 }
00536
00537
00538
00539
00540 if (_camera->moving == true) {
00541 if (InputManager->UpState()) {
00542 if (InputManager->LeftState()) {
00543 _camera->SetDirection(NORTHWEST);
00544 }
00545 else if (InputManager->RightState()) {
00546 _camera->SetDirection(NORTHEAST);
00547 }
00548 else {
00549 _camera->SetDirection(NORTH);
00550 }
00551 }
00552 else if (InputManager->DownState()) {
00553 if (InputManager->LeftState()) {
00554 _camera->SetDirection(SOUTHWEST);
00555 }
00556 else if (InputManager->RightState()) {
00557 _camera->SetDirection(SOUTHEAST);
00558 }
00559 else {
00560 _camera->SetDirection(SOUTH);
00561 }
00562 }
00563 else if (InputManager->LeftState()) {
00564 _camera->SetDirection(WEST);
00565 }
00566 else if (InputManager->RightState()) {
00567 _camera->SetDirection(EAST);
00568 }
00569 }
00570 }
00571
00572
00573
00574 MapObject* MapMode::_FindNearestObject(const VirtualSprite* sprite) {
00575
00576 float top, bottom, left, right;
00577
00578
00579 if (sprite->direction & FACING_NORTH) {
00580 bottom = sprite->ComputeYLocation() - sprite->coll_height;
00581 top = bottom - 3.0f;
00582 left = sprite->ComputeXLocation() - sprite->coll_half_width;
00583 right = sprite->ComputeXLocation() + sprite->coll_half_width;
00584 }
00585 else if (sprite->direction & FACING_SOUTH) {
00586 top = sprite->ComputeYLocation();
00587 bottom = top + 3.0f;
00588 left = sprite->ComputeXLocation() - sprite->coll_half_width;
00589 right = sprite->ComputeXLocation() + sprite->coll_half_width;
00590 }
00591 else if (sprite->direction & FACING_WEST) {
00592 right = sprite->ComputeXLocation() - sprite->coll_half_width;
00593 left = right - 3.0f;
00594 bottom = sprite->ComputeYLocation();
00595 top = bottom - sprite->coll_height;
00596 }
00597 else if (sprite->direction & FACING_EAST) {
00598 left = sprite->ComputeXLocation() + sprite->coll_half_width;
00599 right = left + 3.0f;
00600 bottom = sprite->ComputeYLocation();
00601 top = bottom - sprite->coll_height;
00602 }
00603 else {
00604 if (MAP_DEBUG)
00605 cerr << "MAP ERROR: sprite was set to invalid direction in MapMode::_FindNearestObject()" << endl;
00606 return NULL;
00607 }
00608
00609
00610 vector<MapObject*> valid_objects;
00611
00612 MapObject* closest = NULL;
00613
00614
00615 for (map<uint16, MapObject*>::iterator i = _all_objects.begin(); i != _all_objects.end(); i++) {
00616 MapObject* obj = i->second;
00617 if( obj == sprite )
00618 continue;
00619
00620
00621 if (obj->context & sprite->context == 0)
00622 continue;
00623
00624
00625 float other_x_location = obj->ComputeXLocation();
00626 float other_y_location = obj->ComputeYLocation();
00627
00628
00629 if (!(other_x_location - obj->coll_half_width > right
00630 || other_x_location + obj->coll_half_width < left)) {
00631
00632 if (!(other_y_location - obj->coll_height > bottom
00633 || other_y_location < top )) {
00634
00635 valid_objects.push_back(obj);
00636 }
00637 }
00638 }
00639
00640
00641 if (valid_objects.empty()) {
00642 return NULL;
00643 }
00644 else if (valid_objects.size() == 1) {
00645 return valid_objects[0];
00646 }
00647
00648
00649
00650
00651
00652
00653 float source_x = sprite->ComputeXLocation();
00654 float source_y = sprite->ComputeYLocation();
00655
00656 closest = valid_objects[0];
00657 float min_distance = fabs(source_x - closest->ComputeXLocation())
00658 + fabs(source_y - closest->ComputeYLocation());
00659
00660
00661 for (uint32 i = 1; i < valid_objects.size(); i++) {
00662 float dist = fabs(source_x - valid_objects[i]->ComputeXLocation())
00663 + fabs(source_y - valid_objects[i]->ComputeYLocation());
00664 if (dist < min_distance) {
00665 closest = valid_objects[i];
00666 min_distance = dist;
00667 }
00668 }
00669 return closest;
00670 }
00671
00672
00673
00674 bool MapMode::_DetectCollision(VirtualSprite* sprite) {
00675
00676
00677
00678
00679 float x_location = sprite->ComputeXLocation();
00680 float y_location = sprite->ComputeYLocation();
00681
00682
00683 float cr_left = x_location - sprite->coll_half_width;
00684 float cr_right = x_location + sprite->coll_half_width;
00685 float cr_top = y_location - sprite->coll_height;
00686
00687
00688
00689
00690 if (cr_left < 0.0f || cr_top < 0.0f || cr_right >= static_cast<float>(_num_grid_cols) ||
00691 y_location >= static_cast<float>(_num_grid_rows)) {
00692 return true;
00693 }
00694
00695
00696 if (sprite->no_collision == true) {
00697 return false;
00698 }
00699
00700
00701 vector<MapObject*>* objects;
00702
00703 if (sprite->sky_object == false) {
00704
00705
00706
00707
00708
00709 for (uint32 r = static_cast<uint32>(cr_top); r <= static_cast<uint32>(y_location); r++) {
00710 for (uint32 c = static_cast<uint32>(cr_left); c <= static_cast<uint32>(cr_right); c++) {
00711 if (_map_grid[r][c] & sprite->context > 0) {
00712 return true;
00713 }
00714 }
00715 }
00716 objects = &_ground_objects;
00717 }
00718 else {
00719 objects = &_sky_objects;
00720 }
00721
00722
00723
00724 for (uint32 i = 0; i < objects->size(); i++) {
00725
00726 if ((*objects)[i]->object_id != sprite->object_id
00727 && !(*objects)[i]->no_collision
00728 && (*objects)[i]->context & sprite->context > 0 )
00729 {
00730
00731 float other_x_location = (*objects)[i]->ComputeXLocation();
00732 float other_y_location = (*objects)[i]->ComputeYLocation();;
00733
00734
00735 if (!(other_x_location - (*objects)[i]->coll_half_width > cr_right
00736 || other_x_location + (*objects)[i]->coll_half_width < cr_left)) {
00737
00738 if (!(other_y_location - (*objects)[i]->coll_height > y_location || other_y_location < cr_top )) {
00739
00740 if (sprite->GetType() == ENEMY_TYPE && (*objects)[i] == _camera) {
00741 EnemySprite *enemy = reinterpret_cast<EnemySprite*>(sprite);
00742 if (enemy->IsHostile()) {
00743 enemy->ChangeStateDead();
00744 BattleMode *BM = new BattleMode();
00745 BM->AddMusic(enemy->GetBattleMusicTheme());
00746 ModeManager->Push(BM);
00747 const vector<uint32>& enemy_party = enemy->RetrieveRandomParty();
00748 for (uint32 i = 0; i < enemy_party.size(); i++) {
00749 BM->AddEnemy(enemy_party[i]);
00750 }
00751 return false;
00752 }
00753 }
00754
00755 if ((*objects)[i]->GetType() == ENEMY_TYPE && sprite == _camera) {
00756 EnemySprite *enemy = reinterpret_cast<EnemySprite*>((*objects)[i]);
00757 if (enemy->IsHostile()) {
00758 enemy->ChangeStateDead();
00759 BattleMode *BM = new BattleMode();
00760 BM->AddMusic(enemy->GetBattleMusicTheme());
00761 ModeManager->Push(BM);
00762 const vector<uint32>& enemy_party = enemy->RetrieveRandomParty();
00763 for (uint32 i = 0; i < enemy_party.size(); i++) {
00764 BM->AddEnemy(enemy_party[i]);
00765 }
00766 return false;
00767 }
00768 }
00769
00770 return true;
00771 }
00772 }
00773
00774 }
00775 }
00776
00777
00778 return false;
00779 }
00780
00781
00782
00783 void MapMode::_FindPath(const VirtualSprite* sprite, std::vector<PathNode>& path, const PathNode& dest) {
00784
00785 std::vector<PathNode> open_list;
00786 std::vector<PathNode> closed_list;
00787
00788
00789 PathNode source_node(static_cast<int16>(sprite->y_position), static_cast<int16>(sprite->x_position));
00790
00791
00792 PathNode best_node;
00793
00794 PathNode nodes[8];
00795
00796
00797 uint32 x_delta, y_delta;
00798
00799 int16 x_span, y_span;
00800
00801 int16 g_add;
00802
00803 path.clear();
00804 x_span = static_cast<int16>(sprite->coll_half_width);
00805 y_span = static_cast<int16>(sprite->coll_height);
00806
00807
00808 if (source_node == dest) {
00809 if (MAP_DEBUG)
00810 cerr << "MAP ERROR: source node is same as destination in MapMode::_FindPath()" << endl;
00811 return;
00812 }
00813
00814
00815 if ((dest.col - x_span < 0) || (dest.row - y_span < 0) ||
00816 (dest.col + x_span >= (_num_grid_cols)) || (dest.row >= (_num_grid_rows))) {
00817 if (MAP_DEBUG)
00818 cerr << "MAP ERROR: sprite can not move to destination node on path because it exceeds map boundaries" << endl;
00819 return;
00820 }
00821 for (int16 r = dest.row - y_span; r < dest.row; r++) {
00822 for (int16 c = dest.col - x_span; c < dest.col + x_span; c++) {
00823 if (_map_grid[r][c] & sprite->context > 0) {
00824 if (MAP_DEBUG)
00825 cerr << "MAP ERROR: sprite can not move to destination node on path because one or more grid tiles are unwalkable" << endl;
00826 return;
00827 }
00828 }
00829 }
00830
00831 open_list.push_back(source_node);
00832
00833 while (!open_list.empty()) {
00834
00835 sort(open_list.begin(), open_list.end());
00836 best_node = open_list.back();
00837 open_list.pop_back();
00838 closed_list.push_back(best_node);
00839
00840
00841 if (best_node == dest) {
00842 break;
00843 }
00844
00845
00846 nodes[0].row = closed_list.back().row - 1; nodes[0].col = closed_list.back().col;
00847 nodes[1].row = closed_list.back().row + 1; nodes[1].col = closed_list.back().col;
00848 nodes[2].row = closed_list.back().row; nodes[2].col = closed_list.back().col - 1;
00849 nodes[3].row = closed_list.back().row; nodes[3].col = closed_list.back().col + 1;
00850 nodes[4].row = closed_list.back().row - 1; nodes[4].col = closed_list.back().col - 1;
00851 nodes[5].row = closed_list.back().row - 1; nodes[5].col = closed_list.back().col + 1;
00852 nodes[6].row = closed_list.back().row + 1; nodes[6].col = closed_list.back().col - 1;
00853 nodes[7].row = closed_list.back().row + 1; nodes[7].col = closed_list.back().col + 1;
00854
00855
00856 for (uint8 i = 0; i < 8; ++i) {
00857
00858 if ((nodes[i].col - x_span < 0) || (nodes[i].row - y_span < 0) ||
00859 (nodes[i].col + x_span >= _num_grid_cols) || (nodes[i].row >= _num_grid_rows)) {
00860 continue;
00861 }
00862
00863
00864 bool continue_loop = true;
00865 for (int16 r = nodes[i].row - y_span; r < nodes[i].row && continue_loop; r++) {
00866 for (int16 c = nodes[i].col - x_span; c < nodes[i].col + x_span; c++) {
00867 if (_map_grid[r][c] & sprite->context > 0) {
00868 continue_loop = false;
00869 break;
00870 }
00871 }
00872 }
00873 if (continue_loop == false) {
00874 continue;
00875 }
00876
00877
00878 if (find(closed_list.begin(), closed_list.end(), nodes[i]) != closed_list.end()) {
00879 continue;
00880 }
00881
00882
00883
00884
00885 if (i < 4)
00886 g_add = 10;
00887 else
00888 g_add = 14;
00889
00890
00891 nodes[i].parent_row = best_node.row;
00892 nodes[i].parent_col = best_node.col;
00893 nodes[i].g_score = best_node.g_score + g_add;
00894
00895
00896 vector<PathNode>::iterator iter = find(open_list.begin(), open_list.end(), nodes[i]);
00897 if (iter != open_list.end()) {
00898
00899 if (iter->g_score > nodes[i].g_score) {
00900 iter->g_score = nodes[i].g_score;
00901 iter->f_score = nodes[i].g_score + iter->h_score;
00902 iter->parent_row = nodes[i].parent_row;
00903 iter->parent_col = nodes[i].parent_col;
00904 }
00905 }
00906
00907 else {
00908
00909 x_delta = abs(dest.col - nodes[i].col);
00910 y_delta = abs(dest.row - nodes[i].row);
00911 if (x_delta > y_delta)
00912 nodes[i].h_score = 14 * y_delta + 10 * (x_delta - y_delta);
00913 else
00914 nodes[i].h_score = 14 * x_delta + 10 * (y_delta - x_delta);
00915
00916 nodes[i].f_score = nodes[i].g_score + nodes[i].h_score;
00917 open_list.push_back(nodes[i]);
00918 }
00919 }
00920 }
00921
00922 if (open_list.empty()) {
00923 if (MAP_DEBUG)
00924 cerr << "MAP ERROR: could not find path to destination" << endl;
00925 path.push_back( source_node );
00926 return;
00927 }
00928
00929
00930 path.push_back(closed_list.back());
00931 int16 parent_row = closed_list.back().parent_row;
00932 int16 parent_col = closed_list.back().parent_col;
00933
00934 closed_list.pop_back();
00935
00936
00937 for (vector<PathNode>::iterator iter = closed_list.end() - 1; iter != closed_list.begin(); --iter) {
00938 if ( iter->col == parent_col && iter->row == parent_row ) {
00939 path.push_back(*iter);
00940 parent_col = iter->parent_col;
00941 parent_row = iter->parent_row;
00942 }
00943 }
00944 std::reverse( path.begin(), path.end() );
00945 }
00946
00947
00948
00949
00950
00951 #define __MAP_CHANGE_1__
00952 #define __MAP_CHANGE_2__
00953
00954
00955
00956 void MapMode::_CalculateDrawInfo() {
00957
00958
00959
00960 #ifdef __MAP_CHANGE_1__
00961 static float x (_draw_info.tile_x_start);
00962 static float y (_draw_info.tile_y_start);
00963
00964
00965 {
00966 _draw_info.tile_x_start = x;
00967 _draw_info.tile_y_start = y;
00968 }
00969 #endif
00970
00971
00972
00973
00974 float camera_x = _camera->ComputeXLocation();
00975 float camera_y = _camera->ComputeYLocation();
00976
00977
00978 _draw_info.tile_x_start = 1.0f - _camera->x_offset;
00979 if (IsOddNumber(_camera->x_position))
00980 _draw_info.tile_x_start -= 1.0f;
00981
00982 _draw_info.tile_y_start = 2.0f - _camera->y_offset;
00983 if (IsOddNumber(_camera->y_position))
00984 _draw_info.tile_y_start -= 1.0f;
00985
00986
00987 _draw_info.num_draw_cols = TILE_COLS + 1;
00988 _draw_info.num_draw_rows = TILE_ROWS + 1;
00989
00990
00991 _draw_info.starting_col = (_camera->x_position / 2) - HALF_TILE_COLS;
00992 _draw_info.starting_row = (_camera->y_position / 2) - HALF_TILE_ROWS;
00993
00994
00995
00996 _draw_info.top_edge = camera_y - HALF_SCREEN_ROWS;
00997 _draw_info.bottom_edge = camera_y + HALF_SCREEN_ROWS;
00998 _draw_info.left_edge = camera_x - HALF_SCREEN_COLS;
00999 _draw_info.right_edge = camera_x + HALF_SCREEN_COLS;
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009 if (_draw_info.starting_col < 0) {
01010 _draw_info.starting_col = 0;
01011 _draw_info.tile_x_start = 1.0f;
01012 _draw_info.left_edge = 0.0f;
01013 _draw_info.right_edge = SCREEN_COLS;
01014 }
01015
01016 else if (_draw_info.starting_col + TILE_COLS >= _num_tile_cols) {
01017 _draw_info.starting_col = static_cast<int16>(_num_tile_cols - TILE_COLS);
01018 _draw_info.tile_x_start = 1.0f;
01019 _draw_info.right_edge = static_cast<float>(_num_grid_cols);
01020 _draw_info.left_edge = _draw_info.right_edge - SCREEN_COLS;
01021 }
01022
01023
01024 if (_draw_info.starting_row < 0) {
01025 _draw_info.starting_row = 0;
01026 _draw_info.tile_y_start = 2.0f;
01027 _draw_info.top_edge = 0.0f;
01028 _draw_info.bottom_edge = SCREEN_ROWS;
01029 }
01030
01031 else if (_draw_info.starting_row + TILE_ROWS >= _num_tile_rows) {
01032 _draw_info.starting_row = static_cast<int16>(_num_tile_rows - TILE_ROWS);
01033 _draw_info.tile_y_start = 2.0f;
01034 _draw_info.bottom_edge = static_cast<float>(_num_grid_rows);
01035 _draw_info.top_edge = _draw_info.bottom_edge - SCREEN_ROWS;
01036 }
01037
01038
01039 if (IsFloatInRange(_draw_info.tile_x_start, 0.999f, 1.001f)) {
01040 _draw_info.num_draw_cols--;
01041 }
01042 if (IsFloatInRange(_draw_info.tile_y_start, 1.999f, 2.001f)) {
01043 _draw_info.num_draw_rows--;
01044 }
01045
01046
01047
01048 #ifdef __MAP_CHANGE_1__
01049 double y_resolution;
01050 double x_resolution;
01051
01052 float x2 (_draw_info.tile_x_start);
01053 float y2 (_draw_info.tile_y_start);
01054
01055
01056 {
01057 VideoManager->GetPixelSize(x_resolution, y_resolution);
01058 x_resolution = abs(x_resolution);
01059 y_resolution = abs(y_resolution);
01060
01061 _draw_info.tile_x_start = FloorToFloatMultiple (_draw_info.tile_x_start, x_resolution);
01062 _draw_info.tile_y_start = FloorToFloatMultiple (_draw_info.tile_y_start, y_resolution);
01063
01064 if (x2 - _draw_info.tile_x_start > x_resolution*0.5f)
01065 _draw_info.tile_x_start += x_resolution;
01066 if (y2 - _draw_info.tile_y_start > y_resolution*0.5f)
01067 _draw_info.tile_y_start += y_resolution;
01068 }
01069 #endif
01070
01071 #if defined(__MAP_CHANGE_1__) && defined(__MAP_CHANGE_2__)
01072
01073 {
01074 _draw_info.left_edge = FloorToFloatMultiple (_draw_info.left_edge, x_resolution);
01075 _draw_info.top_edge = FloorToFloatMultiple (_draw_info.top_edge, y_resolution);
01076
01077 if (camera_x - HALF_SCREEN_COLS - _draw_info.left_edge > x_resolution*0.5f)
01078 _draw_info.left_edge += x_resolution;
01079 if (camera_y - HALF_SCREEN_ROWS - _draw_info.top_edge > y_resolution*0.5f)
01080 _draw_info.top_edge += y_resolution;
01081
01082 _draw_info.right_edge = _draw_info.left_edge + 2*SCREEN_COLS;
01083 _draw_info.bottom_edge = _draw_info.top_edge + 2*SCREEN_ROWS;
01084 }
01085 #endif
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096 }
01097
01098
01099
01100 void MapMode::Draw() {
01101 _CalculateDrawInfo();
01102
01103
01104
01105
01106
01107 VideoManager->SetDrawFlags(VIDEO_NO_BLEND, 0);
01108 VideoManager->Move(_draw_info.tile_x_start, _draw_info.tile_y_start);
01109 for (uint32 r = static_cast<uint32>(_draw_info.starting_row);
01110 r < static_cast<uint32>(_draw_info.starting_row + _draw_info.num_draw_rows); r++) {
01111 for (uint32 c = static_cast<uint32>(_draw_info.starting_col);
01112 c < static_cast<uint32>(_draw_info.starting_col + _draw_info.num_draw_cols); c++) {
01113 if (_tile_grid[r][c].lower_layer >= 0) {
01114 _tile_images[_tile_grid[r][c].lower_layer]->Draw();
01115 }
01116 VideoManager->MoveRelative(2.0f, 0.0f);
01117 }
01118 VideoManager->MoveRelative(-static_cast<float>(_draw_info.num_draw_cols * 2), 2.0f);
01119 }
01120
01121
01122 VideoManager->SetDrawFlags(VIDEO_BLEND, 0);
01123 VideoManager->Move(_draw_info.tile_x_start, _draw_info.tile_y_start);
01124 for (uint32 r = static_cast<uint32>(_draw_info.starting_row);
01125 r < static_cast<uint32>(_draw_info.starting_row + _draw_info.num_draw_rows); r++) {
01126
01127 for (uint32 c = static_cast<uint32>(_draw_info.starting_col);
01128 c < static_cast<uint32>(_draw_info.starting_col + _draw_info.num_draw_cols); c++) {
01129 if (_tile_grid[r][c].middle_layer >= 0) {
01130 _tile_images[_tile_grid[r][c].middle_layer]->Draw();
01131 }
01132 VideoManager->MoveRelative(2.0f, 0.0f);
01133 }
01134
01135 VideoManager->MoveRelative(static_cast<float>(_draw_info.num_draw_cols * -2), 2.0f);
01136 }
01137
01138
01139 for (uint32 i = 0; i < _ground_objects.size(); i++) {
01140 if (_ground_objects[i]->draw_on_second_pass == false) {
01141 _ground_objects[i]->Draw();
01142 }
01143 }
01144
01145
01146 for (uint32 i = 0; i < _pass_objects.size(); i++) {
01147 _pass_objects[i]->Draw();
01148 }
01149
01150
01151 for (uint32 i = 0; i < _ground_objects.size(); i++) {
01152 if (_ground_objects[i]->draw_on_second_pass == true) {
01153 _ground_objects[i]->Draw();
01154 }
01155 }
01156
01157
01158 VideoManager->Move(_draw_info.tile_x_start, _draw_info.tile_y_start);
01159 for (uint32 r = static_cast<uint32>(_draw_info.starting_row);
01160 r < static_cast<uint32>(_draw_info.starting_row + _draw_info.num_draw_rows); r++) {
01161 for (uint32 c = static_cast<uint32>(_draw_info.starting_col);
01162 c < static_cast<uint32>(_draw_info.starting_col + _draw_info.num_draw_cols); c++) {
01163 if (_tile_grid[r][c].upper_layer >= 0) {
01164 _tile_images[_tile_grid[r][c].upper_layer]->Draw();
01165 }
01166 VideoManager->MoveRelative(2.0f, 0.0f);
01167 }
01168 VideoManager->MoveRelative(-static_cast<float>(_draw_info.num_draw_cols * 2), 2.0f);
01169 }
01170
01171
01172 for (uint32 i = 0; i < _sky_objects.size(); i++) {
01173 _sky_objects[i]->Draw();
01174 }
01175
01176
01177
01178
01179
01180 if (_map_state == DIALOGUE) {
01181 _dialogue_manager->Draw();
01182 }
01183
01184 if (_intro_timer.IsFinished() == false) {
01185 uint32 time = _intro_timer.GetTimeExpired();
01186 Color blend(1.0f, 1.0f, 1.0f, 1.0f);
01187 if (time < 2000) {
01188 blend.SetAlpha((static_cast<float>(time) / 2000.0f));
01189 }
01190 else if (time > 5000) {
01191 blend.SetAlpha(1.0f - static_cast<float>(time - 5000) / 2000.0f);
01192 }
01193 VideoManager->PushState();
01194 VideoManager->SetCoordSys(0.0f, 1024.0f, 768.0f, 0.0f);
01195 VideoManager->SetDrawFlags(VIDEO_X_CENTER, VIDEO_Y_CENTER, 0);
01196 VideoManager->Move(512.0f, 100.0f);
01197 VideoManager->DrawImage(_location_graphic, blend);
01198 VideoManager->MoveRelative(0.0f, -80.0f);
01199 VideoManager->SetTextColor(blend);
01200 VideoManager->DrawText(_map_name);
01201 VideoManager->PopState();
01202 }
01203 }
01204
01205
01206
01207 uint16 MapMode::_GetGeneratedObjectID() {
01208 return ++_lastID;
01209 }
01210
01211
01212
01213
01214
01215 void MapMode::_AddGroundObject(private_map::MapObject *obj) {
01216 _ground_objects.push_back(obj);
01217 _all_objects.insert(make_pair(obj->object_id, obj));
01218 }
01219
01220
01221
01222 void MapMode::_AddPassObject(private_map::MapObject *obj) {
01223 _pass_objects.push_back(obj);
01224 _all_objects.insert(make_pair(obj->object_id, obj));
01225 }
01226
01227
01228
01229 void MapMode::_AddSkyObject(private_map::MapObject *obj) {
01230 _sky_objects.push_back(obj);
01231 _all_objects.insert(make_pair(obj->object_id, obj));
01232 }
01233
01234 void MapMode::_AddZone(private_map::MapZone *zone) {
01235 _zones.push_back(zone);
01236 }
01237
01238 }