00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "mapcharacter.h"
00023 #include "map_event.h"
00024 #include "time_event.h"
00025 #include "event_handler.h"
00026 #include "landmap.h"
00027 #include "win_manager.h"
00028
00029 using namespace std;
00030
00031
00032
00033 mapcharacter::mapcharacter () : mapsquare_walkable_area (), character_base (), event_list ()
00034 {
00035 submap_ = posx_ = posy_ = offx_ = offy_ = 0;
00036 refmap = NULL;
00037 anim.resize (NBR_MOVES);
00038 for (u_int16 i = 0; i < NBR_MOVES; i++)
00039 anim[i] = new animation;
00040 current_move = STAND_NORTH;
00041 previous_move = NO_MOVE;
00042
00043 saying = NULL;
00044
00045 schedule_activated = true;
00046 action_activated = true;
00047 goal_reached_ = true;
00048
00049 schedule_args = NULL;
00050 action_args = NULL;
00051
00052 callback = NULL;
00053 }
00054
00055 mapcharacter::~mapcharacter ()
00056 {
00057 clear ();
00058 for (u_int16 i = 0; i < anim.size (); i++)
00059 delete anim[i];
00060 anim.clear ();
00061 }
00062
00063 void mapcharacter::clear ()
00064 {
00065 event_list::clear ();
00066
00067 if (saying) delete saying;
00068
00069 for (u_int16 i = 0; i < anim.size (); i++)
00070 anim[i]->clear ();
00071
00072 mapsquare_walkable_area::clear ();
00073
00074 schedule.clear ();
00075 action.clear ();
00076
00077 filename_ = "";
00078
00079 Py_XDECREF (schedule_args);
00080 schedule_args = NULL;
00081
00082 Py_XDECREF (action_args);
00083 action_args = NULL;
00084 schedule_file_ = "";
00085 action_file_ = "";
00086
00087 if (callback) delete callback;
00088 }
00089
00090 s_int8 mapcharacter::get (igzstream& file)
00091 {
00092 int i;
00093
00094 for (i = 0; i < NBR_MOVES; i++)
00095 {
00096 anim[i]->get (file);
00097 anim[i]->stop ();
00098 }
00099
00100 mapsquare_walkable_area::get (file);
00101
00102 return 0;
00103 }
00104
00105 s_int8 mapcharacter::load (string fname)
00106 {
00107 string s = MAPCHAR_DIR;
00108
00109 s += fname;
00110 igzstream file (s);
00111 if (!file.is_open ())
00112 return -1;
00113
00114 s_int8 retvalue;
00115 if (fileops::get_version (file, 1, 1, s))
00116 retvalue = get (file);
00117 file.close ();
00118 filename_ = fname;
00119
00120 return 0;
00121 }
00122
00123 s_int8 mapcharacter::put (ogzstream& file) const
00124 {
00125 int i;
00126
00127 for (i = 0; i < NBR_MOVES; i++)
00128 {
00129 anim[i]->put (file);
00130 }
00131
00132 mapsquare_walkable_area::put (file);
00133
00134 return 0;
00135 }
00136
00137 s_int8 mapcharacter::save (string fname) const
00138 {
00139 string s = MAPCHAR_DIR;
00140
00141 s += fname;
00142 ogzstream file (s);
00143 if (!file.is_open ())
00144 return -1;
00145
00146 s_int8 retvalue;
00147 fileops::put_version (file, 1);
00148 retvalue = put (file);
00149 file.close ();
00150
00151 return 0;
00152 }
00153
00154 s_int8 mapcharacter::get_state (igzstream& file)
00155 {
00156 string t;
00157 bool b;
00158 u_int16 current_move__;
00159 s_int8 offx__, offy__;
00160
00161 remove_from_pos ();
00162
00163 t << file;
00164 load (t);
00165
00166
00167 current_move__ << file;
00168 previous_move << file;
00169 submap_ << file;
00170 posx_ << file;
00171 posy_ << file;
00172 offx__ << file;
00173 offy__ << file;
00174
00175 jump_to (submap (), posx (), posy ());
00176 set_offset (offx__, offy__);
00177
00178 current_move = current_move__;
00179
00180
00181 mypath.get_state (file);
00182
00183 mypath.refmap = refmap;
00184
00185 pathindex << file;
00186 goal_reached_ << file;
00187
00188
00189 PyObject * args;
00190 t << file;
00191 b << file;
00192 args = NULL;
00193 if (b) args = python::get_tuple (file);
00194 set_schedule (t, args);
00195 Py_XDECREF (args);
00196 b << file;
00197 set_schedule_active (b);
00198
00199
00200 t << file;
00201 b << file;
00202 args = NULL;
00203 if (b) args = python::get_tuple (file);
00204 set_action (t, args);
00205 Py_XDECREF (args);
00206 b << file;
00207 set_action_active (b);
00208
00209
00210 py_callback::instance = schedule.get_instance (false);
00211 return event_list::get_state (file);
00212 }
00213
00214 s_int8 mapcharacter::put_state (ogzstream& file) const
00215 {
00216
00217 filename_ >> file;
00218
00219
00220 current_move >> file;
00221 previous_move >> file;
00222 submap_ >> file;
00223 posx_ >> file;
00224 posy_ >> file;
00225 offx_ >> file;
00226 offy_ >> file;
00227
00228
00229 mypath.put_state (file);
00230 pathindex >> file;
00231 goal_reached_ >> file;
00232
00233
00234 schedule_file () >> file;
00235 if (schedule_args)
00236 {
00237 true >> file;
00238 python::put_tuple (schedule_args, file);
00239 }
00240 else false >> file;
00241 is_schedule_activated () >> file;
00242
00243
00244 action_file () >> file;
00245 if (action_args)
00246 {
00247 true >> file;
00248 python::put_tuple (action_args, file);
00249 }
00250 else false >> file;
00251 is_action_activated () >> file;
00252
00253
00254 event_list::put_state (file);
00255
00256 return 0;
00257 }
00258
00259 void mapcharacter::set_map (landmap * m)
00260 {
00261 if (mymap ()) return;
00262
00263 m->mapchar.push_back (this);
00264
00265 refmap = m;
00266 }
00267
00268 void mapcharacter::remove_from_map ()
00269 {
00270 if (!mymap ()) return;
00271
00272 leave_position ();
00273
00274 vector <mapcharacter *>::iterator i;
00275 for (i = mymap ()->mapchar.begin (); (*i) != this; i++);
00276 mymap ()->mapchar.erase (i);
00277
00278 refmap = NULL;
00279 }
00280
00281 void mapcharacter::remove_from_pos ()
00282 {
00283 leave_position ();
00284 }
00285
00286 void mapcharacter::jump_to (u_int16 smap, u_int16 x, u_int16 y,
00287 u_int16 pos)
00288 {
00289 leave_position ();
00290 set_pos (smap, x, y);
00291 set_offset (0, 0);
00292
00293 switch (pos)
00294 {
00295 case STAND_NORTH:
00296 stand_north ();
00297 break;
00298 case STAND_SOUTH:
00299 stand_south ();
00300 break;
00301 case STAND_WEST:
00302 stand_west ();
00303 break;
00304 case STAND_EAST:
00305 stand_east ();
00306 break;
00307 default:
00308 stand ();
00309 break;
00310 }
00311
00312 enter_event evt;
00313 evt.submap = submap ();
00314 evt.x = posx ();
00315 evt.y = posy ();
00316 evt.c = this;
00317 evt.dir = pos;
00318 event_handler::raise_event (&evt);
00319 }
00320
00321 void mapcharacter::stand ()
00322 {
00323 if (current_move >= WALK_NORTH && current_move != NO_MOVE)
00324 {
00325 previous_move = current_move;
00326 current_move -= WALK_NORTH;
00327 }
00328 }
00329
00330 void mapcharacter::stand_north ()
00331 {
00332 previous_move = current_move;
00333 current_move = STAND_NORTH;
00334 }
00335
00336 void mapcharacter::stand_south ()
00337 {
00338 previous_move = current_move;
00339 current_move = STAND_SOUTH;
00340 }
00341
00342 void mapcharacter::stand_east ()
00343 {
00344 previous_move = current_move;
00345 current_move = STAND_EAST;
00346 }
00347
00348 void mapcharacter::stand_west ()
00349 {
00350 previous_move = current_move;
00351 current_move = STAND_WEST;
00352 }
00353
00354 bool mapcharacter::can_go_north () const
00355 {
00356 if (!posy ())
00357 return false;
00358 u_int16 i, j;
00359 u_int16 sx = (posx () - base_x () < 0) ? 0 : posx () - base_x ();
00360 u_int16 sy = (posy () - base_y () < 0) ? 0 : posy () - base_y ();
00361 s_int16 ax = sx - (posx () - base_x ());
00362 s_int16 ay = sy - (posy () - base_y ());
00363 u_int16 ex =
00364 (posx () - base_x () + area_length () >
00365 refmap->submap[submap ()]->area_length ()) ? refmap->submap[submap ()]->area_length ()
00366 : posx () - base_x () + area_length ();
00367 u_int16 ey =
00368 (posy () - base_y () + area_height () >
00369 refmap->submap[submap ()]->area_height ()) ? refmap->submap[submap ()]->area_height ()
00370 : posy () - base_y () + area_height ();
00371
00372 for (j = sy; j < ey; j++)
00373 for (i = sx; i < ex; i++)
00374 {
00375 if (get_square (i - sx + ax, j - sy + ay)->get_walkable ())
00376 continue;
00377 if (!j)
00378 continue;
00379 if (!(refmap->submap[submap ()]->area[i][j].is_walkable_north () &&
00380 refmap->submap[submap ()]->area[i][j - 1].is_walkable_south ()
00381 && refmap->submap[submap ()]->area[i][j - 1].is_free ()))
00382 return false;
00383 }
00384 return true;
00385 }
00386
00387 bool mapcharacter::can_go_south () const
00388 {
00389 if (posy () == refmap->submap[submap ()]->area_height () - 1)
00390 return false;
00391 u_int16 i, j;
00392 u_int16 sx = (posx () - base_x () < 0) ? 0 : posx () - base_x ();
00393 u_int16 sy = (posy () - base_y () < 0) ? 0 : posy () - base_y ();
00394 s_int16 ax = sx - (posx () - base_x ());
00395 s_int16 ay = sy - (posy () - base_y ());
00396 u_int16 ex =
00397 (posx () - base_x () + area_length () >=
00398 refmap->submap[submap ()]->area_length ()) ? refmap->submap[submap ()]->area_length ()
00399 : posx () - base_x () + area_length ();
00400 u_int16 ey =
00401 (posy () - base_y () + area_height () >=
00402 refmap->submap[submap ()]->area_height ()) ? refmap->submap[submap ()]->area_height ()
00403 : posy () - base_y () + area_height ();
00404
00405 for (j = sy; j < ey; j++)
00406 for (i = sx; i < ex; i++)
00407 {
00408 if (get_square (i - sx + ax, j - sy + ay)->get_walkable ())
00409 continue;
00410 if (j == refmap->submap[submap ()]->area_height () - 1)
00411 continue;
00412 if (!(refmap->submap[submap ()]->area[i][j].is_walkable_south () &&
00413 refmap->submap[submap ()]->area[i][j +
00414 1].is_walkable_north ()
00415 && refmap->submap[submap ()]->area[i][j + 1].is_free ()))
00416 return false;
00417 }
00418 return true;
00419 }
00420
00421 bool mapcharacter::can_go_east () const
00422 {
00423 if (posx () == refmap->submap[submap ()]->area_length () - 1)
00424 return false;
00425 u_int16 i, j;
00426 u_int16 sx = (posx () - base_x () < 0) ? 0 : posx () - base_x ();
00427 u_int16 sy = (posy () - base_y () < 0) ? 0 : posy () - base_y ();
00428 s_int16 ax = sx - (posx () - base_x ());
00429 s_int16 ay = sy - (posy () - base_y ());
00430 u_int16 ex =
00431 (posx () - base_x () + area_length () >=
00432 refmap->submap[submap ()]->area_length ()) ? refmap->submap[submap ()]->area_length ()
00433 : posx () - base_x () + area_length ();
00434 u_int16 ey =
00435 (posy () - base_y () + area_height () >=
00436 refmap->submap[submap ()]->area_height ()) ? refmap->submap[submap ()]->area_height ()
00437 : posy () - base_y () + area_height ();
00438
00439 for (j = sy; j < ey; j++)
00440 for (i = sx; i < ex; i++)
00441 {
00442 if (get_square (i - sx + ax, j - sy + ay)->get_walkable ())
00443 continue;
00444 if (i == refmap->submap[submap ()]->area_length () - 1)
00445 continue;
00446 if (!(refmap->submap[submap ()]->area[i][j].is_walkable_east () &&
00447 refmap->submap[submap ()]->area[i + 1][j].is_walkable_west ()
00448 && refmap->submap[submap ()]->area[i + 1][j].is_free ()))
00449 return false;
00450 }
00451 return true;
00452 }
00453
00454 bool mapcharacter::can_go_west () const
00455 {
00456 if (!posx ())
00457 return false;
00458 u_int16 i, j;
00459 u_int16 sx = (posx () - base_x () < 0) ? 0 : posx () - base_x ();
00460 u_int16 sy = (posy () - base_y () < 0) ? 0 : posy () - base_y ();
00461 s_int16 ax = sx - (posx () - base_x ());
00462 s_int16 ay = sy - (posy () - base_y ());
00463 u_int16 ex =
00464 (posx () - base_x () + area_length () >
00465 refmap->submap[submap ()]->area_length ()) ? refmap->submap[submap ()]->area_length ()
00466 : posx () - base_x () + area_length ();
00467 u_int16 ey =
00468 (posy () - base_y () + area_height () >
00469 refmap->submap[submap ()]->area_height ()) ? refmap->submap[submap ()]->area_height ()
00470 : posy () - base_y () + area_height ();
00471
00472 for (j = sy; j < ey; j++)
00473 for (i = sx; i < ex; i++)
00474 {
00475 if (get_square (i - sx + ax, j - sy + ay)->get_walkable ())
00476 continue;
00477 if (!i)
00478 continue;
00479 if (!(refmap->submap[submap ()]->area[i][j].is_walkable_west () &&
00480 refmap->submap[submap ()]->area[i - 1][j].is_walkable_east ()
00481 && refmap->submap[submap ()]->area[i - 1][j].is_free ()))
00482 return false;
00483 }
00484 return true;
00485 }
00486
00487 bool mapcharacter::go_north ()
00488 {
00489 if (current_move < WALK_NORTH)
00490 {
00491 bool ret = can_go_north ();
00492 previous_move = current_move;
00493 if (ret)
00494 current_move = WALK_NORTH;
00495 else current_move = STAND_NORTH;
00496 return ret;
00497 }
00498 return false;
00499 }
00500
00501 bool mapcharacter::go_south ()
00502 {
00503 if (current_move < WALK_NORTH)
00504 {
00505 bool ret = can_go_south ();
00506 previous_move = current_move;
00507 if (ret)
00508 current_move = WALK_SOUTH;
00509 else current_move = STAND_SOUTH;
00510 return ret;
00511 }
00512 return false;
00513 }
00514
00515 bool mapcharacter::go_east ()
00516 {
00517 if (current_move < WALK_NORTH)
00518 {
00519 bool ret = can_go_east ();
00520 previous_move = current_move;
00521 if (ret)
00522 current_move = WALK_EAST;
00523 else current_move = STAND_EAST;
00524 return ret;
00525 }
00526 return false;
00527 }
00528
00529 bool mapcharacter::go_west ()
00530 {
00531 if (current_move < WALK_NORTH)
00532 {
00533 bool ret = can_go_west ();
00534 previous_move = current_move;
00535 if (ret)
00536 current_move = WALK_WEST;
00537 else current_move = STAND_WEST;
00538 return ret;
00539 }
00540 return false;
00541 }
00542
00543 bool mapcharacter::set_goal (u_int16 x, u_int16 y, u_int16 dir)
00544 {
00545 mypath.refmap = mymap ();
00546 mypath.submap = submap ();
00547 mypath.start.x = posx ();
00548 mypath.start.y = posy ();
00549 mypath.goal.x = x;
00550 mypath.goal.y = y;
00551 mypath.dir = dir;
00552 pathindex = 0;
00553 goal_reached_ = false;
00554
00555 return mypath.calculate ();
00556 }
00557
00558 void mapcharacter::set_callback (PyObject *cb, PyObject *args)
00559 {
00560 if (callback) delete callback;
00561 callback = new py_callback (cb, args);
00562 }
00563
00564 void mapcharacter::time_callback (string delay, PyObject *cb, PyObject *args)
00565 {
00566 time_event *ev = new time_event (delay);
00567 ev->set_callback (cb, args);
00568 add_event (ev);
00569 }
00570
00571 void mapcharacter::time_callback_string (string delay, string cb, PyObject *args)
00572 {
00573 PyObject *instance = schedule.get_instance (false);
00574
00575
00576 if (instance == NULL)
00577 {
00578 fprintf (stderr, "*** error: mapcharacter::time_callback: Invalid instance!");
00579 return;
00580 }
00581
00582 PyObject *callback = PyObject_GetAttrString (instance, (char *) cb.c_str ());
00583
00584 if (!PyCallable_Check (callback))
00585 {
00586 fprintf (stderr, "*** error: mapcharacter::time_callback: Setting callback ' %s' failed!", cb.c_str ());
00587 }
00588 else
00589 {
00590 time_event *ev = new time_event (delay);
00591 ev->set_callback (callback, args);
00592 add_event (ev);
00593 }
00594
00595 Py_XDECREF (callback);
00596 }
00597
00598 bool mapcharacter::follow_path ()
00599 {
00600
00601 if (offx () || offy ())
00602 return false;
00603
00604
00605 if (pathindex < mypath.nbr_moves ())
00606 {
00607 u_int16 dir = mypath.get_move (pathindex);
00608 u_int8 success = 0;
00609
00610
00611 switch (dir)
00612 {
00613 case WALK_NORTH:
00614 if (go_north ()) success = 1;
00615 break;
00616
00617 case WALK_SOUTH:
00618 if (go_south ()) success = 1;
00619 break;
00620
00621 case WALK_WEST:
00622 if (go_west ()) success = 1;
00623 break;
00624
00625 case WALK_EAST:
00626 if (go_east ()) success = 1;
00627 break;
00628 }
00629
00630
00631 if (!success)
00632 {
00633 mypath.start.x = posx ();
00634 mypath.start.y = posy ();
00635 mypath.submap = submap ();
00636 mypath.calculate ();
00637 pathindex = 0;
00638 }
00639 else pathindex++;
00640 }
00641 else
00642 {
00643 switch (mypath.dir)
00644 {
00645 case STAND_NORTH:
00646 stand_north ();
00647 break;
00648 case STAND_SOUTH:
00649 stand_south ();
00650 break;
00651 case STAND_WEST:
00652 stand_west ();
00653 break;
00654 case STAND_EAST:
00655 stand_east ();
00656 break;
00657 }
00658
00659
00660
00661 goal_reached_ = true;
00662 if (callback) callback->callback_func0 ();
00663 return true;
00664 }
00665 return false;
00666 }
00667
00668 void mapcharacter::stop_moving ()
00669 {
00670 set_goal (posx (), posy ());
00671 }
00672
00673 bool mapcharacter::goal_reached ()
00674 {
00675 return goal_reached_;
00676 }
00677
00678 void mapcharacter::look_invert (u_int16 p)
00679 {
00680 switch (p)
00681 {
00682 case STAND_NORTH:
00683 stand_south ();
00684 break;
00685 case STAND_SOUTH:
00686 stand_north ();
00687 break;
00688 case STAND_EAST:
00689 stand_west ();
00690 break;
00691 case STAND_WEST:
00692 stand_east ();
00693 break;
00694 }
00695 }
00696
00697 mapcharacter *mapcharacter::whosnext () const
00698 {
00699 switch (current_move)
00700 {
00701 case STAND_NORTH:
00702 if (posy () == 0)
00703 return NULL;
00704 return refmap->submap[submap ()]->area[posx ()][posy () - 1].whoshere ();
00705 break;
00706 case STAND_SOUTH:
00707 if (posy () == refmap->submap[submap ()]->area_height () - 1)
00708 return NULL;
00709 return refmap->submap[submap ()]->area[posx ()][posy () + 1].whoshere ();
00710 break;
00711 case STAND_WEST:
00712 if (posx () == 0)
00713 return NULL;
00714 return refmap->submap[submap ()]->area[posx () - 1][posy ()].whoshere ();
00715 break;
00716 case STAND_EAST:
00717 if (posx () == refmap->submap[submap ()]->area_length () - 1)
00718 return NULL;
00719 return refmap->submap[submap ()]->area[posx () + 1][posy ()].whoshere ();
00720 break;
00721 }
00722 return NULL;
00723 }
00724
00725 bool mapcharacter::do_stuff (string method, PyObject *args)
00726 {
00727 if (!schedule.has_attribute (method)) return false;
00728 else schedule.call_method (method, args);
00729
00730 return true;
00731 }
00732
00733 void mapcharacter::set_schedule (string file, PyObject * args)
00734 {
00735
00736 schedule.clear ();
00737 Py_XDECREF (schedule_args);
00738 schedule_args = NULL;
00739
00740
00741 if (file != "")
00742 {
00743 Py_XINCREF (args);
00744 schedule_args = args;
00745 u_int16 argssize = args == NULL ? 1 : PyTuple_Size (args) + 1;
00746 PyObject * theargs;
00747
00748 theargs = PyTuple_New (argssize);
00749
00750
00751
00752 PyTuple_SetItem (theargs, 0, python::pass_instance (this, "mapcharacter"));
00753 for (u_int16 i = 1; i < argssize; i++)
00754 {
00755 PyObject * intref = PyTuple_GetItem (args, i - 1);
00756 Py_INCREF (intref);
00757 PyTuple_SetItem (theargs, i, intref);
00758 }
00759 schedule.create_instance ("schedules.mapcharacters." + file, file, theargs);
00760 Py_DECREF (theargs);
00761
00762 if (!schedule.has_attribute ("run"))
00763 set_schedule_active (false);
00764 }
00765 schedule_file_ = file;
00766 }
00767
00768 void mapcharacter::set_action (string file, PyObject * args)
00769 {
00770
00771 action.clear ();
00772 Py_XDECREF (action_args);
00773 action_args = NULL;
00774
00775 if (file != "")
00776 {
00777 Py_XINCREF (args);
00778 action_args = args;
00779 u_int16 argssize = args == NULL ? 1 : PyTuple_Size (args) + 1;
00780 PyObject * theargs;
00781
00782 theargs = PyTuple_New (argssize);
00783
00784
00785
00786 PyTuple_SetItem (theargs, 0, python::pass_instance (this, "mapcharacter"));
00787 for (u_int16 i = 1; i < argssize; i++)
00788 {
00789 PyObject * intref = PyTuple_GetItem (args, i - 1);
00790 Py_INCREF (intref);
00791 PyTuple_SetItem (theargs, i, intref);
00792 }
00793 action.create_instance ("actions." + file, file, theargs);
00794 Py_DECREF (theargs);
00795 }
00796 action_file_ = file;
00797 }
00798
00799 bool mapcharacter::update ()
00800 {
00801 update_move ();
00802
00803 if (is_schedule_activated ())
00804 schedule.run ();
00805
00806
00807 if (!goal_reached ())
00808 follow_path ();
00809
00810 if (previous_move != NO_MOVE && previous_move != current_move)
00811 {
00812 anim[previous_move]->stop ();
00813 anim[previous_move]->rewind ();
00814 anim[current_move]->play ();
00815 }
00816
00817 if (saying && !saying->update ())
00818 {
00819 delete saying;
00820 saying = NULL;
00821 }
00822
00823 return true;
00824 }
00825
00826 void mapcharacter::launch_action (mapcharacter * requester)
00827 {
00828 PyObject *args = PyTuple_New (1);
00829 PyTuple_SetItem (args, 0, python::pass_instance (requester, "mapcharacter"));
00830 if (is_action_activated ()) action.run (args);
00831 Py_DECREF (args);
00832 }
00833
00834 void mapcharacter::draw (s_int16 x, s_int16 y, const drawing_area * da_opt, surface * target) const
00835 {
00836 anim[current_move]->draw (x, y, da_opt, target);
00837 }
00838
00839 void mapcharacter::draw_bubble (s_int16 x, s_int16 y, const drawing_area * da_opt,
00840 surface * target) const
00841 {
00842 if (saying)
00843 {
00844 s_int16 dx = x - (saying->drawing_area::length () >> 1) + (anim[current_move]->length () >> 1);
00845 s_int16 dy = y - (saying->drawing_area::height ()) + 5;
00846
00847 if (dx < 4) dx = 4;
00848 else if (dx + saying->drawing_area::length () > da_opt->x () + da_opt->length () - 4)
00849 dx = da_opt->x () + da_opt->length () - saying->drawing_area::length () - 4;
00850
00851 saying->move (dx, dy);
00852 saying->assign_drawing_area (da_opt);
00853 saying->draw ();
00854 saying->detach_drawing_area ();
00855 }
00856 }
00857
00858 mapcharacter & mapcharacter::operator = (const mapcharacter & src)
00859 {
00860 u_int16 i;
00861
00862 clear ();
00863
00864 (mapsquare_walkable_area&) (*this) = (mapsquare_walkable_area&) src;
00865 (character_base&) (*this) = (character_base&) src;
00866
00867 for (i = 0; i < NBR_MOVES; i++)
00868 (*anim[i]) = (*src.anim[i]);
00869
00870 schedule = src.schedule;
00871
00872 action = src.action;
00873
00874 current_move = src.currentmove ();
00875 if (src.mymap ())
00876 {
00877 set_map (src.mymap ());
00878 set_pos (src.submap (), src.posx (), src.posy ());
00879 set_offset (src.offx (), src.offy ());
00880 }
00881
00882 filename_ = src.filename_;
00883
00884 return *this;
00885 }
00886
00887
00888
00889
00890
00891
00892 void mapcharacter::occupy (u_int16 smap, u_int16 px, u_int16 py)
00893 {
00894 mapsquare_char mschar;
00895
00896 list <mapsquare_char>::iterator it;
00897 u_int16 sx = (px - base_x () < 0) ? 0 : px - base_x ();
00898 u_int16 sy = (py - base_y () < 0) ? 0 : py - base_y ();
00899 u_int16 ex = (sx + area_length () > refmap->submap[smap]->area_length ()) ?
00900 refmap->submap[smap]->area_length () : sx + area_length ();
00901 u_int16 ey = (sy + area_height () > refmap->submap[smap]->area_height ()) ?
00902 refmap->submap[smap]->area_height () : sy + area_height ();
00903 u_int16 i, j;
00904
00905
00906 mschar.mchar = this;
00907 mschar.is_base = true;
00908 mschar.x = px;
00909 mschar.y = py;
00910 mschar.walkable =
00911 get_square (base_x (), base_y ())->get_walkable () == ALL_WALKABLE;
00912
00913 refmap->submap[smap]->area[px][py].mapchars.push_back (mschar);
00914 it = --refmap->submap[smap]->area[px][py].mapchars.end ();
00915 it->base_tile = it;
00916 mschar.base_tile = it;
00917 mschar.is_base = false;
00918
00919
00920 for (i = sx; i < ex; i++)
00921 for (j = sy; j < ey; j++)
00922 if (i != px || j != py)
00923 {
00924 mschar.x = i;
00925 mschar.y = j;
00926 mschar.walkable =
00927 get_square (sx + base_x () - px, sy + base_y () - py)->
00928 get_walkable () == ALL_WALKABLE;
00929 refmap->submap[smap]->area[i][j].mapchars.push_back (mschar);
00930 }
00931 }
00932
00933 void mapcharacter::leave (u_int16 smap, u_int16 px, u_int16 py)
00934 {
00935 list <mapsquare_char>::iterator it;
00936 list <mapsquare_char>::iterator e;
00937
00938 u_int16 sx = (px - base_x () < 0) ? 0 : px - base_x ();
00939 u_int16 sy = (py - base_y () < 0) ? 0 : py - base_y ();
00940 u_int16 ex = (sx + area_length () > refmap->submap[smap]->area_length ()) ?
00941 refmap->submap[smap]->area_length () : sx + area_length ();
00942 u_int16 ey = (sy + area_height () > refmap->submap[smap]->area_height ()) ?
00943 refmap->submap[smap]->area_height () : sy + area_height ();
00944 u_int16 i, j;
00945
00946
00947 for (i = sx; i < ex; i++)
00948 for (j = sy; j < ey; j++)
00949 {
00950 it = refmap->submap[smap]->area[i][j].mapchars.begin ();
00951 e = refmap->submap[smap]->area[i][j].mapchars.end ();
00952
00953 while (it != e && it->mchar != this)
00954 it++;
00955 if (it != e)
00956 refmap->submap[smap]->area[px][py].mapchars.erase (it);
00957 }
00958 }
00959
00960 void mapcharacter::leave_position ()
00961 {
00962 leave (submap (), posx (), posy ());
00963 switch (current_move)
00964 {
00965 case WALK_NORTH:
00966 case WALK_SOUTH:
00967 leave (submap (), posx (), posy () - 1);
00968 break;
00969
00970 case WALK_WEST:
00971 case WALK_EAST:
00972 leave (submap (), posx () - 1, posy ());
00973 break;
00974 }
00975 }
00976
00977 void mapcharacter::set_pos (u_int16 smap, u_int16 x, u_int16 y)
00978 {
00979
00980 submap_ = smap;
00981 posx_ = x;
00982 posy_ = y;
00983
00984
00985 occupy (submap (), posx (), posy ());
00986 }
00987
00988 void mapcharacter::update_move ()
00989 {
00990 if (refmap)
00991 switch (currentmove ())
00992 {
00993 case WALK_NORTH:
00994 if (!offy ())
00995 {
00996 if (!can_go_north ())
00997 {
00998 stand_north ();
00999 break;
01000 }
01001 leave_event evt;
01002
01003 evt.submap = submap ();
01004 evt.x = posx ();
01005 evt.y = posy ();
01006 evt.c = this;
01007 evt.dir = WALK_NORTH;
01008 event_handler::raise_event (&evt);
01009
01010 occupy (submap (), posx (), posy () - 1);
01011 set_offset (offx (), offy () - 1);
01012 }
01013
01014 set_offset (offx (), offy () - 1);
01015
01016 if (offy () == -MAPSQUARE_SIZE)
01017 {
01018 leave (submap (), posx (), posy ());
01019 leave (submap (), posx (), posy () - 1);
01020 set_pos (submap (), posx (), posy () - 1);
01021 set_offset (offx (), 0);
01022 stand_north ();
01023
01024 enter_event evt;
01025
01026 evt.submap = submap ();
01027 evt.x = posx ();
01028 evt.y = posy ();
01029 evt.c = this;
01030 evt.dir = WALK_NORTH;
01031 event_handler::raise_event (&evt);
01032 }
01033 break;
01034 case WALK_SOUTH:
01035 if (!offy ())
01036 {
01037 if (!can_go_south ())
01038 {
01039 stand_south ();
01040 break;
01041 }
01042 leave_event evt;
01043
01044 evt.submap = submap ();
01045 evt.x = posx ();
01046 evt.y = posy ();
01047 evt.c = this;
01048 evt.dir = WALK_SOUTH;
01049 event_handler::raise_event (&evt);
01050
01051 leave (submap (), posx (), posy ());
01052 occupy (submap (), posx (), posy ());
01053 set_pos (submap (), posx (), posy () + 1);
01054 set_offset (0, -(MAPSQUARE_SIZE - 1));
01055 }
01056 else
01057 {
01058 set_offset (offx (), offy () + 1);
01059
01060 if (!offy ())
01061 {
01062 leave (submap (), posx (), posy () - 1);
01063 stand_south ();
01064
01065 enter_event evt;
01066 evt.submap = submap ();
01067 evt.x = posx ();
01068 evt.y = posy ();
01069 evt.c = this;
01070 evt.dir = WALK_SOUTH;
01071 event_handler::raise_event (&evt);
01072 }
01073 }
01074 break;
01075 case WALK_WEST:
01076 if (!offx ())
01077 {
01078 if (!can_go_west ())
01079 {
01080 stand_west ();
01081 break;
01082 }
01083 leave_event evt;
01084
01085 evt.submap = submap ();
01086 evt.x = posx ();
01087 evt.y = posy ();
01088 evt.c = this;
01089 evt.dir = WALK_WEST;
01090 event_handler::raise_event (&evt);
01091
01092 occupy (submap (), posx () - 1, posy ());
01093 }
01094 set_offset (offx () -1, offy ());
01095 if (offx () == -MAPSQUARE_SIZE)
01096 {
01097 leave (submap (), posx (), posy ());
01098 leave (submap (), posx () - 1, posy ());
01099 set_pos (submap (), posx () - 1, posy ());
01100 set_offset (0, offy ());
01101 stand_west ();
01102
01103 enter_event evt;
01104 evt.submap = submap ();
01105 evt.x = posx ();
01106 evt.y = posy ();
01107 evt.c = this;
01108 evt.dir = WALK_WEST;
01109 event_handler::raise_event (&evt);
01110 }
01111 break;
01112 case WALK_EAST:
01113 if (!offx ())
01114 {
01115 if (!can_go_east ())
01116 {
01117 stand_east ();
01118 break;
01119 }
01120 leave_event evt;
01121
01122 evt.submap = submap ();
01123 evt.x = posx ();
01124 evt.y = posy ();
01125 evt.c = this;
01126 evt.dir = WALK_EAST;
01127 event_handler::raise_event (&evt);
01128
01129 leave (submap (), posx (), posy ());
01130 occupy (submap (), posx (), posy ());
01131 set_pos (submap (), posx () + 1, posy ());
01132 set_offset (-(MAPSQUARE_SIZE - 1), 0);
01133 }
01134 else
01135 {
01136 set_offset (offx () + 1, offy ());
01137 if (!offx ())
01138 {
01139 leave (submap (), posx () - 1, posy ());
01140 stand_east ();
01141
01142 enter_event evt;
01143 evt.submap = submap ();
01144 evt.x = posx ();
01145 evt.y = posy ();
01146 evt.c = this;
01147 evt.dir = WALK_EAST;
01148 event_handler::raise_event (&evt);
01149 }
01150 }
01151 break;
01152 }
01153 anim[current_move]->update ();
01154 }
01155
01156 void mapcharacter::speak (const string & text)
01157 {
01158 if (saying)
01159 delete saying;
01160
01161 string col;
01162 switch (get_color ())
01163 {
01164 case 1: col = "yellow"; break;
01165 case 2: col = "red"; break;
01166 case 3: col = "violet"; break;
01167 case 4: col = "blue"; break;
01168 case 5: col = "green"; break;
01169 default: col = "white"; break;
01170 }
01171
01172 saying = new text_bubble (text, col, "original");
01173 }