Adonthell  0.4
mapcharacter.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 1999/2000/2001/2002 Alexandre Courbot
3  Part of the Adonthell Project <http://adonthell.nongnu.org>
4 
5  Adonthell is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  Adonthell is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with Adonthell. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 /**
20  * @file mapcharacter.cc
21  *
22  * @author Alexandre Courbot <alexandrecourbot@linuxgames.com>
23  * @brief Defines the mapcharacter class.
24  */
25 
26 #include "mapcharacter.h"
27 #include "map_event.h"
28 #include "time_event.h"
29 #include "event_handler.h"
30 #include "landmap.h"
31 #include "win_manager.h"
32 
33 using namespace std;
34 
35 
36 // Public methods
38 {
39  submap_ = posx_ = posy_ = offx_ = offy_ = 0;
40  refmap = NULL;
41  anim.resize (NBR_MOVES);
42  for (u_int16 i = 0; i < NBR_MOVES; i++)
43  anim[i] = new animation;
44  current_move = STAND_NORTH;
45  previous_move = NO_MOVE;
46 
47  saying = NULL;
48 
49  schedule_activated = true;
50  action_activated = true;
51  goal_reached_ = true;
52 
53  schedule_args = NULL;
54  action_args = NULL;
55 
56  callback = NULL;
57 }
58 
60 {
61  clear ();
62  for (u_int16 i = 0; i < anim.size (); i++)
63  delete anim[i];
64  anim.clear ();
65 }
66 
68 {
70 
71  if (saying) delete saying;
72 
73  for (u_int16 i = 0; i < anim.size (); i++)
74  anim[i]->clear ();
75 
77 
78  schedule.clear ();
79  action.clear ();
80 
81  filename_ = "";
82 
83  Py_XDECREF (schedule_args);
84  schedule_args = NULL;
85 
86  Py_XDECREF (action_args);
87  action_args = NULL;
88  schedule_file_ = "";
89  action_file_ = "";
90 
91  if (callback) delete callback;
92 }
93 
95 {
96  int i;
97 
98  for (i = 0; i < NBR_MOVES; i++)
99  {
100  anim[i]->get (file);
101  anim[i]->stop ();
102  }
103 
105 
106  return 0;
107 }
108 
110 {
111  string s = MAPCHAR_DIR;
112 
113  s += fname;
114  igzstream file (s);
115  if (!file.is_open ())
116  return -1;
117 
118  s_int8 retvalue;
119  if (fileops::get_version (file, 1, 1, s))
120  retvalue = get (file);
121  file.close ();
122  filename_ = fname;
123 
124  return 0;
125 }
126 
128 {
129  int i;
130 
131  for (i = 0; i < NBR_MOVES; i++)
132  {
133  anim[i]->put (file);
134  }
135 
137 
138  return 0;
139 }
140 
141 s_int8 mapcharacter::save (string fname) const
142 {
143  string s = MAPCHAR_DIR;
144 
145  s += fname;
146  ogzstream file (s);
147  if (!file.is_open ())
148  return -1;
149 
150  s_int8 retvalue;
151  fileops::put_version (file, 1);
152  retvalue = put (file);
153  file.close ();
154 
155  return 0;
156 }
157 
159 {
160  string t;
161  bool b;
162  u_int16 current_move__;
163  s_int8 offx__, offy__;
164 
165  remove_from_pos ();
166 
167  t << file;
168  load (t);
169 
170  // Reads the data members
171  current_move__ << file;
172  previous_move << file;
173  submap_ << file;
174  posx_ << file;
175  posy_ << file;
176  offx__ << file;
177  offy__ << file;
178 
179  jump_to (submap (), posx (), posy ());
180  set_offset (offx__, offy__);
181 
182  current_move = current_move__;
183 
184  // Get the path state
185  mypath.get_state (file);
186  // The map must be attached manually for now! :(
187  mypath.refmap = refmap;
188 
189  pathindex << file;
190  goal_reached_ << file;
191 
192  // Schedule state
193  PyObject * args;
194  t << file;
195  b << file;
196  args = NULL;
197  if (b) args = python::get_tuple (file);
198  set_schedule (t, args);
199  Py_XDECREF (args);
200  b << file;
202 
203  // Action state
204  t << file;
205  b << file;
206  args = NULL;
207  if (b) args = python::get_tuple (file);
208  set_action (t, args);
209  Py_XDECREF (args);
210  b << file;
211  set_action_active (b);
212 
213  // get the events
214  py_callback::instance = schedule.get_instance (false);
215  return event_list::get_state (file);
216 }
217 
219 {
220  // Write the mapcharacter's file name
221  filename_ >> file;
222 
223  // Write the data members
224  current_move >> file;
225  previous_move >> file;
226  submap_ >> file;
227  posx_ >> file;
228  posy_ >> file;
229  offx_ >> file;
230  offy_ >> file;
231 
232  // Save the path state
233  mypath.put_state (file);
234  pathindex >> file;
235  goal_reached_ >> file;
236 
237  // Save the schedule script state
238  schedule_file () >> file;
239  if (schedule_args)
240  {
241  true >> file;
242  python::put_tuple (schedule_args, file);
243  }
244  else false >> file;
245  is_schedule_activated () >> file;
246 
247  // Save the action script state
248  action_file () >> file;
249  if (action_args)
250  {
251  true >> file;
252  python::put_tuple (action_args, file);
253  }
254  else false >> file;
255  is_action_activated () >> file;
256 
257  // save the events
258  event_list::put_state (file);
259 
260  return 0;
261 }
262 
264 {
265  if (mymap ()) return;
266 
267  m->mapchar.push_back (this);
268 
269  refmap = m;
270 }
271 
273 {
274  if (!mymap ()) return;
275 
276  leave_position ();
277 
278  vector <mapcharacter *>::iterator i;
279  for (i = mymap ()->mapchar.begin (); (*i) != this; i++);
280  mymap ()->mapchar.erase (i);
281 
282  refmap = NULL;
283 }
284 
286 {
287  leave_position ();
288 }
289 
291  u_int16 pos)
292 {
293  leave_position ();
294  set_pos (smap, x, y);
295  set_offset (0, 0);
296 
297  switch (pos)
298  {
299  case STAND_NORTH:
300  stand_north ();
301  break;
302  case STAND_SOUTH:
303  stand_south ();
304  break;
305  case STAND_WEST:
306  stand_west ();
307  break;
308  case STAND_EAST:
309  stand_east ();
310  break;
311  default:
312  stand ();
313  break;
314  }
315 
316  enter_event evt;
317  evt.submap = submap ();
318  evt.x = posx ();
319  evt.y = posy ();
320  evt.c = this;
321  evt.dir = pos;
323 }
324 
326 {
327  if (current_move >= WALK_NORTH && current_move != NO_MOVE)
328  {
329  previous_move = current_move;
330  current_move -= WALK_NORTH;
331  }
332 }
333 
335 {
336  previous_move = current_move;
337  current_move = STAND_NORTH;
338 }
339 
341 {
342  previous_move = current_move;
343  current_move = STAND_SOUTH;
344 }
345 
347 {
348  previous_move = current_move;
349  current_move = STAND_EAST;
350 }
351 
353 {
354  previous_move = current_move;
355  current_move = STAND_WEST;
356 }
357 
359 {
360  if (!posy ())
361  return false;
362  u_int16 i, j;
363  u_int16 sx = (posx () - base_x () < 0) ? 0 : posx () - base_x ();
364  u_int16 sy = (posy () - base_y () < 0) ? 0 : posy () - base_y ();
365  s_int16 ax = sx - (posx () - base_x ());
366  s_int16 ay = sy - (posy () - base_y ());
367  u_int16 ex =
368  (posx () - base_x () + area_length () >
369  refmap->submap[submap ()]->area_length ()) ? refmap->submap[submap ()]->area_length ()
370  : posx () - base_x () + area_length ();
371  u_int16 ey =
372  (posy () - base_y () + area_height () >
373  refmap->submap[submap ()]->area_height ()) ? refmap->submap[submap ()]->area_height ()
374  : posy () - base_y () + area_height ();
375 
376  for (j = sy; j < ey; j++)
377  for (i = sx; i < ex; i++)
378  {
379  if (get_square (i - sx + ax, j - sy + ay)->get_walkable ())
380  continue;
381  if (!j)
382  continue;
383  if (!(refmap->submap[submap ()]->area[i][j].is_walkable_north () &&
384  refmap->submap[submap ()]->area[i][j - 1].is_walkable_south ()
385  && refmap->submap[submap ()]->area[i][j - 1].is_free ()))
386  return false;
387  }
388  return true;
389 }
390 
392 {
393  if (posy () == refmap->submap[submap ()]->area_height () - 1)
394  return false;
395  u_int16 i, j;
396  u_int16 sx = (posx () - base_x () < 0) ? 0 : posx () - base_x ();
397  u_int16 sy = (posy () - base_y () < 0) ? 0 : posy () - base_y ();
398  s_int16 ax = sx - (posx () - base_x ());
399  s_int16 ay = sy - (posy () - base_y ());
400  u_int16 ex =
401  (posx () - base_x () + area_length () >=
402  refmap->submap[submap ()]->area_length ()) ? refmap->submap[submap ()]->area_length ()
403  : posx () - base_x () + area_length ();
404  u_int16 ey =
405  (posy () - base_y () + area_height () >=
406  refmap->submap[submap ()]->area_height ()) ? refmap->submap[submap ()]->area_height ()
407  : posy () - base_y () + area_height ();
408 
409  for (j = sy; j < ey; j++)
410  for (i = sx; i < ex; i++)
411  {
412  if (get_square (i - sx + ax, j - sy + ay)->get_walkable ())
413  continue;
414  if (j == refmap->submap[submap ()]->area_height () - 1)
415  continue;
416  if (!(refmap->submap[submap ()]->area[i][j].is_walkable_south () &&
417  refmap->submap[submap ()]->area[i][j +
418  1].is_walkable_north ()
419  && refmap->submap[submap ()]->area[i][j + 1].is_free ()))
420  return false;
421  }
422  return true;
423 }
424 
426 {
427  if (posx () == refmap->submap[submap ()]->area_length () - 1)
428  return false;
429  u_int16 i, j;
430  u_int16 sx = (posx () - base_x () < 0) ? 0 : posx () - base_x ();
431  u_int16 sy = (posy () - base_y () < 0) ? 0 : posy () - base_y ();
432  s_int16 ax = sx - (posx () - base_x ());
433  s_int16 ay = sy - (posy () - base_y ());
434  u_int16 ex =
435  (posx () - base_x () + area_length () >=
436  refmap->submap[submap ()]->area_length ()) ? refmap->submap[submap ()]->area_length ()
437  : posx () - base_x () + area_length ();
438  u_int16 ey =
439  (posy () - base_y () + area_height () >=
440  refmap->submap[submap ()]->area_height ()) ? refmap->submap[submap ()]->area_height ()
441  : posy () - base_y () + area_height ();
442 
443  for (j = sy; j < ey; j++)
444  for (i = sx; i < ex; i++)
445  {
446  if (get_square (i - sx + ax, j - sy + ay)->get_walkable ())
447  continue;
448  if (i == refmap->submap[submap ()]->area_length () - 1)
449  continue;
450  if (!(refmap->submap[submap ()]->area[i][j].is_walkable_east () &&
451  refmap->submap[submap ()]->area[i + 1][j].is_walkable_west ()
452  && refmap->submap[submap ()]->area[i + 1][j].is_free ()))
453  return false;
454  }
455  return true;
456 }
457 
459 {
460  if (!posx ())
461  return false;
462  u_int16 i, j;
463  u_int16 sx = (posx () - base_x () < 0) ? 0 : posx () - base_x ();
464  u_int16 sy = (posy () - base_y () < 0) ? 0 : posy () - base_y ();
465  s_int16 ax = sx - (posx () - base_x ());
466  s_int16 ay = sy - (posy () - base_y ());
467  u_int16 ex =
468  (posx () - base_x () + area_length () >
469  refmap->submap[submap ()]->area_length ()) ? refmap->submap[submap ()]->area_length ()
470  : posx () - base_x () + area_length ();
471  u_int16 ey =
472  (posy () - base_y () + area_height () >
473  refmap->submap[submap ()]->area_height ()) ? refmap->submap[submap ()]->area_height ()
474  : posy () - base_y () + area_height ();
475 
476  for (j = sy; j < ey; j++)
477  for (i = sx; i < ex; i++)
478  {
479  if (get_square (i - sx + ax, j - sy + ay)->get_walkable ())
480  continue;
481  if (!i)
482  continue;
483  if (!(refmap->submap[submap ()]->area[i][j].is_walkable_west () &&
484  refmap->submap[submap ()]->area[i - 1][j].is_walkable_east ()
485  && refmap->submap[submap ()]->area[i - 1][j].is_free ()))
486  return false;
487  }
488  return true;
489 }
490 
492 {
493  if (current_move < WALK_NORTH)
494  {
495  bool ret = can_go_north ();
496  previous_move = current_move;
497  if (ret)
498  current_move = WALK_NORTH;
499  else current_move = STAND_NORTH;
500  return ret;
501  }
502  return false;
503 }
504 
506 {
507  if (current_move < WALK_NORTH)
508  {
509  bool ret = can_go_south ();
510  previous_move = current_move;
511  if (ret)
512  current_move = WALK_SOUTH;
513  else current_move = STAND_SOUTH;
514  return ret;
515  }
516  return false;
517 }
518 
520 {
521  if (current_move < WALK_NORTH)
522  {
523  bool ret = can_go_east ();
524  previous_move = current_move;
525  if (ret)
526  current_move = WALK_EAST;
527  else current_move = STAND_EAST;
528  return ret;
529  }
530  return false;
531 }
532 
534 {
535  if (current_move < WALK_NORTH)
536  {
537  bool ret = can_go_west ();
538  previous_move = current_move;
539  if (ret)
540  current_move = WALK_WEST;
541  else current_move = STAND_WEST;
542  return ret;
543  }
544  return false;
545 }
546 
547 bool mapcharacter::set_goal (u_int16 x, u_int16 y, u_int16 dir)
548 {
549  mypath.refmap = mymap ();
550  mypath.submap = submap ();
551  mypath.start.x = posx ();
552  mypath.start.y = posy ();
553  mypath.goal.x = x;
554  mypath.goal.y = y;
555  mypath.dir = dir;
556  pathindex = 0;
557  goal_reached_ = false;
558 
559  return mypath.calculate ();
560 }
561 
562 void mapcharacter::set_callback (PyObject *cb, PyObject *args)
563 {
564  if (callback) delete callback;
565  callback = new py_callback (cb, args);
566 }
567 
568 void mapcharacter::time_callback (string delay, PyObject *cb, PyObject *args)
569 {
570  time_event *ev = new time_event (delay);
571  ev->set_callback (cb, args);
572  add_event (ev);
573 }
574 
575 void mapcharacter::time_callback_string (string delay, string cb, PyObject *args)
576 {
577  PyObject *instance = schedule.get_instance (false);
578 
579  // check that we have a valid instance that contains our callback
580  if (instance == NULL)
581  {
582  fprintf (stderr, "*** error: mapcharacter::time_callback: Invalid instance!");
583  return;
584  }
585 
586  PyObject *callback = PyObject_GetAttrString (instance, (char *) cb.c_str ());
587 
588  if (!PyCallable_Check (callback))
589  {
590  fprintf (stderr, "*** error: mapcharacter::time_callback: Setting callback ' %s' failed!", cb.c_str ());
591  }
592  else
593  {
594  time_event *ev = new time_event (delay);
595  ev->set_callback (callback, args);
596  add_event (ev);
597  }
598 
599  Py_XDECREF (callback);
600 }
601 
602 bool mapcharacter::follow_path ()
603 {
604  // If a movment is engaged, let it finish first.
605  if (offx () || offy ())
606  return false;
607 
608  // If the goal isn't reached yet.
609  if (pathindex < mypath.nbr_moves ())
610  {
611  u_int16 dir = mypath.get_move (pathindex);
612  u_int8 success = 0;
613 
614  // Try to follow the direction
615  switch (dir)
616  {
617  case WALK_NORTH:
618  if (go_north ()) success = 1;
619  break;
620 
621  case WALK_SOUTH:
622  if (go_south ()) success = 1;
623  break;
624 
625  case WALK_WEST:
626  if (go_west ()) success = 1;
627  break;
628 
629  case WALK_EAST:
630  if (go_east ()) success = 1;
631  break;
632  }
633 
634  // Who the fuck is on my way!!?@! I have to find a new path now!
635  if (!success)
636  {
637  mypath.start.x = posx ();
638  mypath.start.y = posy ();
639  mypath.submap = submap ();
640  mypath.calculate ();
641  pathindex = 0;
642  }
643  else pathindex++;
644  }
645  else
646  {
647  switch (mypath.dir)
648  {
649  case STAND_NORTH:
650  stand_north ();
651  break;
652  case STAND_SOUTH:
653  stand_south ();
654  break;
655  case STAND_WEST:
656  stand_west ();
657  break;
658  case STAND_EAST:
659  stand_east ();
660  break;
661  }
662 
663  // goal reached -> notify script (as the script might immediately
664  // set the next goal, we gotta set goal_reached_ before that)
665  goal_reached_ = true;
666  if (callback) callback->callback_func0 ();
667  return true;
668  }
669  return false;
670 }
671 
672 void mapcharacter::stop_moving ()
673 {
674  set_goal (posx (), posy ());
675 }
676 
677 bool mapcharacter::goal_reached ()
678 {
679  return goal_reached_;
680 }
681 
683 {
684  switch (p)
685  {
686  case STAND_NORTH:
687  stand_south ();
688  break;
689  case STAND_SOUTH:
690  stand_north ();
691  break;
692  case STAND_EAST:
693  stand_west ();
694  break;
695  case STAND_WEST:
696  stand_east ();
697  break;
698  }
699 }
700 
702 {
703  switch (current_move)
704  {
705  case STAND_NORTH:
706  if (posy () == 0)
707  return NULL;
708  return refmap->submap[submap ()]->area[posx ()][posy () - 1].whoshere ();
709  break;
710  case STAND_SOUTH:
711  if (posy () == refmap->submap[submap ()]->area_height () - 1)
712  return NULL;
713  return refmap->submap[submap ()]->area[posx ()][posy () + 1].whoshere ();
714  break;
715  case STAND_WEST:
716  if (posx () == 0)
717  return NULL;
718  return refmap->submap[submap ()]->area[posx () - 1][posy ()].whoshere ();
719  break;
720  case STAND_EAST:
721  if (posx () == refmap->submap[submap ()]->area_length () - 1)
722  return NULL;
723  return refmap->submap[submap ()]->area[posx () + 1][posy ()].whoshere ();
724  break;
725  }
726  return NULL;
727 }
728 
729 bool mapcharacter::do_stuff (string method, PyObject *args)
730 {
731  if (!schedule.has_attribute (method)) return false;
732  else schedule.call_method (method, args == Py_None ? NULL : args);
733 
734  return true;
735 }
736 
737 void mapcharacter::set_schedule (string file, PyObject * args)
738 {
739  // Clears the schedule
740  schedule.clear ();
741  Py_XDECREF (schedule_args);
742  schedule_args = NULL;
743 
744  // Set new schedule
745  if (file != "")
746  {
747  if (args == Py_None) args = NULL;
748  Py_XINCREF (args);
749  schedule_args = args;
750  u_int16 argssize = args == NULL ? 1 : PyTuple_Size (args) + 1;
751  PyObject * theargs;
752 
753  theargs = PyTuple_New (argssize);
754 
755  // We can pass_instance directly 'cause PyTuple_SetItem steals a
756  // reference to the result of pass_instance.
757  PyTuple_SetItem (theargs, 0, python::pass_instance (this, "mapcharacter"));
758  for (u_int16 i = 1; i < argssize; i++)
759  {
760  PyObject * intref = PyTuple_GetItem (args, i - 1);
761  Py_INCREF (intref);
762  PyTuple_SetItem (theargs, i, intref);
763  }
764  schedule.create_instance ("schedules.mapcharacters." + file, file, theargs);
765  Py_DECREF (theargs);
766 
767  if (!schedule.has_attribute ("run"))
768  set_schedule_active (false);
769  }
770  schedule_file_ = file;
771 }
772 
773 void mapcharacter::set_action (string file, PyObject * args)
774 {
775  // Clears the action script
776  action.clear ();
777  Py_XDECREF (action_args);
778  action_args = NULL;
779 
780  if (file != "")
781  {
782  Py_XINCREF (args);
783  action_args = args;
784  u_int16 argssize = args == NULL ? 1 : PyTuple_Size (args) + 1;
785  PyObject * theargs;
786 
787  theargs = PyTuple_New (argssize);
788 
789  // We can pass_instance directly 'cause PyTuple_SetItem steals a
790  // reference to the result of pass_instance.
791  PyTuple_SetItem (theargs, 0, python::pass_instance (this, "mapcharacter"));
792  for (u_int16 i = 1; i < argssize; i++)
793  {
794  PyObject * intref = PyTuple_GetItem (args, i - 1);
795  Py_INCREF (intref);
796  PyTuple_SetItem (theargs, i, intref);
797  }
798  action.create_instance ("actions." + file, file, theargs);
799  Py_DECREF (theargs);
800  }
801  action_file_ = file;
802 }
803 
805 {
806  update_move ();
807 
808  if (is_schedule_activated ())
809  schedule.run ();
810 
811  // if we have a goal, then go there!
812  if (!goal_reached ())
813  follow_path ();
814 
815  if (previous_move != NO_MOVE && previous_move != current_move)
816  {
817  anim[previous_move]->stop ();
818  anim[previous_move]->rewind ();
819  anim[current_move]->play ();
820  }
821 
822  if (saying && !saying->update ())
823  {
824  delete saying;
825  saying = NULL;
826  }
827 
828  return true;
829 }
830 
832 {
833  PyObject *args = PyTuple_New (1);
834  PyTuple_SetItem (args, 0, python::pass_instance (requester, "mapcharacter"));
835  if (is_action_activated ()) action.run (args);
836  Py_DECREF (args);
837 }
838 
839 void mapcharacter::draw (s_int16 x, s_int16 y, const drawing_area * da_opt, surface * target) const
840 {
841  anim[current_move]->draw (x, y, da_opt, target);
842 }
843 
844 void mapcharacter::draw_bubble (s_int16 x, s_int16 y, const drawing_area * da_opt,
845  surface * target) const
846 {
847  if (saying)
848  {
849  s_int16 dx = x - (saying->drawing_area::length () >> 1) + (anim[current_move]->length () >> 1);
850  s_int16 dy = y - (saying->drawing_area::height ()) + 5;
851 
852  if (dx < 4) dx = 4;
853  else if (dx + saying->drawing_area::length () > da_opt->x () + da_opt->length () - 4)
854  dx = da_opt->x () + da_opt->length () - saying->drawing_area::length () - 4;
855 
856  saying->move (dx, dy);
857  saying->assign_drawing_area (da_opt);
858  saying->draw ();
859  saying->detach_drawing_area ();
860  }
861 }
862 
864 {
865  u_int16 i;
866 
867  clear ();
868 
870  (character_base&) (*this) = (character_base&) src;
871 
872  for (i = 0; i < NBR_MOVES; i++)
873  (*anim[i]) = (*src.anim[i]);
874 
875  schedule = src.schedule;
876 
877  action = src.action;
878 
879  current_move = src.currentmove ();
880  if (src.mymap ())
881  {
882  set_map (src.mymap ());
883  set_pos (src.submap (), src.posx (), src.posy ());
884  set_offset (src.offx (), src.offy ());
885  }
886 
887  filename_ = src.filename_;
888 
889  return *this;
890 }
891 
892 
893 
894 // Private methods
895 
896 
897 void mapcharacter::occupy (u_int16 smap, u_int16 px, u_int16 py)
898 {
899  mapsquare_char mschar;
900 
901  list <mapsquare_char>::iterator it;
902  u_int16 sx = (px - base_x () < 0) ? 0 : px - base_x ();
903  u_int16 sy = (py - base_y () < 0) ? 0 : py - base_y ();
904  u_int16 ex = (sx + area_length () > refmap->submap[smap]->area_length ()) ?
905  refmap->submap[smap]->area_length () : sx + area_length ();
906  u_int16 ey = (sy + area_height () > refmap->submap[smap]->area_height ()) ?
907  refmap->submap[smap]->area_height () : sy + area_height ();
908  u_int16 i, j;
909 
910  // Placing the base tile first
911  mschar.mchar = this;
912  mschar.is_base = true;
913  mschar.x = px;
914  mschar.y = py;
915  mschar.walkable =
917 
918  refmap->submap[smap]->area[px][py].mapchars.push_back (mschar);
919  it = --refmap->submap[smap]->area[px][py].mapchars.end ();
920  it->base_tile = it;
921  mschar.base_tile = it;
922  mschar.is_base = false;
923 
924  // Ready to place the rest now
925  for (i = sx; i < ex; i++)
926  for (j = sy; j < ey; j++)
927  if (i != px || j != py)
928  {
929  mschar.x = i;
930  mschar.y = j;
931  mschar.walkable =
932  get_square (sx + base_x () - px, sy + base_y () - py)->
933  get_walkable () == ALL_WALKABLE;
934  refmap->submap[smap]->area[i][j].mapchars.push_back (mschar);
935  }
936 }
937 
938 void mapcharacter::leave (u_int16 smap, u_int16 px, u_int16 py)
939 {
940  list <mapsquare_char>::iterator it;
941  list <mapsquare_char>::iterator e;
942 
943  u_int16 sx = (px - base_x () < 0) ? 0 : px - base_x ();
944  u_int16 sy = (py - base_y () < 0) ? 0 : py - base_y ();
945  u_int16 ex = (sx + area_length () > refmap->submap[smap]->area_length ()) ?
946  refmap->submap[smap]->area_length () : sx + area_length ();
947  u_int16 ey = (sy + area_height () > refmap->submap[smap]->area_height ()) ?
948  refmap->submap[smap]->area_height () : sy + area_height ();
949  u_int16 i, j;
950 
951 
952  for (i = sx; i < ex; i++)
953  for (j = sy; j < ey; j++)
954  {
955  it = refmap->submap[smap]->area[i][j].mapchars.begin ();
956  e = refmap->submap[smap]->area[i][j].mapchars.end ();
957 
958  while (it != e && it->mchar != this)
959  it++;
960  if (it != e)
961  refmap->submap[smap]->area[px][py].mapchars.erase (it);
962  }
963 }
964 
965 void mapcharacter::leave_position ()
966 {
967  leave (submap (), posx (), posy ());
968  switch (current_move)
969  {
970  case WALK_NORTH:
971  case WALK_SOUTH:
972  leave (submap (), posx (), posy () - 1);
973  break;
974 
975  case WALK_WEST:
976  case WALK_EAST:
977  leave (submap (), posx () - 1, posy ());
978  break;
979  }
980 }
981 
982 void mapcharacter::set_pos (u_int16 smap, u_int16 x, u_int16 y)
983 {
984  // update character position
985  submap_ = smap;
986  posx_ = x;
987  posy_ = y;
988 
989  // mark the character's place as occupied
990  occupy (submap (), posx (), posy ());
991 }
992 
993 void mapcharacter::update_move ()
994 {
995  if (refmap)
996  switch (currentmove ())
997  {
998  case WALK_NORTH:
999  if (!offy ())
1000  {
1001  if (!can_go_north ())
1002  {
1003  stand_north ();
1004  break;
1005  }
1006  leave_event evt;
1007 
1008  evt.submap = submap ();
1009  evt.x = posx ();
1010  evt.y = posy ();
1011  evt.c = this;
1012  evt.dir = WALK_NORTH;
1014 
1015  occupy (submap (), posx (), posy () - 1);
1016  set_offset (offx (), offy () - 1);
1017  }
1018 
1019  set_offset (offx (), offy () - 1);
1020 
1021  if (offy () == -MAPSQUARE_SIZE)
1022  {
1023  leave (submap (), posx (), posy ());
1024  leave (submap (), posx (), posy () - 1);
1025  set_pos (submap (), posx (), posy () - 1);
1026  set_offset (offx (), 0);
1027  stand_north ();
1028 
1029  enter_event evt;
1030 
1031  evt.submap = submap ();
1032  evt.x = posx ();
1033  evt.y = posy ();
1034  evt.c = this;
1035  evt.dir = WALK_NORTH;
1037  }
1038  break;
1039  case WALK_SOUTH:
1040  if (!offy ())
1041  {
1042  if (!can_go_south ())
1043  {
1044  stand_south ();
1045  break;
1046  }
1047  leave_event evt;
1048 
1049  evt.submap = submap ();
1050  evt.x = posx ();
1051  evt.y = posy ();
1052  evt.c = this;
1053  evt.dir = WALK_SOUTH;
1055 
1056  leave (submap (), posx (), posy ());
1057  occupy (submap (), posx (), posy ());
1058  set_pos (submap (), posx (), posy () + 1);
1059  set_offset (0, -(MAPSQUARE_SIZE - 1));
1060  }
1061  else
1062  {
1063  set_offset (offx (), offy () + 1);
1064 
1065  if (!offy ())
1066  {
1067  leave (submap (), posx (), posy () - 1);
1068  stand_south ();
1069 
1070  enter_event evt;
1071  evt.submap = submap ();
1072  evt.x = posx ();
1073  evt.y = posy ();
1074  evt.c = this;
1075  evt.dir = WALK_SOUTH;
1077  }
1078  }
1079  break;
1080  case WALK_WEST:
1081  if (!offx ())
1082  {
1083  if (!can_go_west ())
1084  {
1085  stand_west ();
1086  break;
1087  }
1088  leave_event evt;
1089 
1090  evt.submap = submap ();
1091  evt.x = posx ();
1092  evt.y = posy ();
1093  evt.c = this;
1094  evt.dir = WALK_WEST;
1096 
1097  occupy (submap (), posx () - 1, posy ());
1098  }
1099  set_offset (offx () -1, offy ());
1100  if (offx () == -MAPSQUARE_SIZE)
1101  {
1102  leave (submap (), posx (), posy ());
1103  leave (submap (), posx () - 1, posy ());
1104  set_pos (submap (), posx () - 1, posy ());
1105  set_offset (0, offy ());
1106  stand_west ();
1107 
1108  enter_event evt;
1109  evt.submap = submap ();
1110  evt.x = posx ();
1111  evt.y = posy ();
1112  evt.c = this;
1113  evt.dir = WALK_WEST;
1115  }
1116  break;
1117  case WALK_EAST:
1118  if (!offx ())
1119  {
1120  if (!can_go_east ())
1121  {
1122  stand_east ();
1123  break;
1124  }
1125  leave_event evt;
1126 
1127  evt.submap = submap ();
1128  evt.x = posx ();
1129  evt.y = posy ();
1130  evt.c = this;
1131  evt.dir = WALK_EAST;
1133 
1134  leave (submap (), posx (), posy ());
1135  occupy (submap (), posx (), posy ());
1136  set_pos (submap (), posx () + 1, posy ());
1137  set_offset (-(MAPSQUARE_SIZE - 1), 0);
1138  }
1139  else
1140  {
1141  set_offset (offx () + 1, offy ());
1142  if (!offx ())
1143  {
1144  leave (submap (), posx () - 1, posy ());
1145  stand_east ();
1146 
1147  enter_event evt;
1148  evt.submap = submap ();
1149  evt.x = posx ();
1150  evt.y = posy ();
1151  evt.c = this;
1152  evt.dir = WALK_EAST;
1154  }
1155  }
1156  break;
1157  }
1158  anim[current_move]->update ();
1159 }
1160 
1161 void mapcharacter::speak (const string & text)
1162 {
1163  if (saying)
1164  delete saying;
1165 
1166  string col;
1167  switch (get_color ())
1168  {
1169  case 1: col = "yellow"; break;
1170  case 2: col = "red"; break;
1171  case 3: col = "violet"; break;
1172  case 4: col = "blue"; break;
1173  case 5: col = "green"; break;
1174  default: col = "white"; break;
1175  }
1176 
1177  saying = new text_bubble (text, col, "original");
1178 }
s_int8 get(igzstream &file)
Loads a mapcharacter from an opened file.
Definition: mapcharacter.cc:94
s_int8 get_state(igzstream &file)
Restore the path&#39;s state from an opened file.
Definition: path.cc:265
s_int8 offy() const
Returns the Y offset of the mapcharacter.
Definition: mapcharacter.h:577
static void raise_event(const event *ev)
Check if an event corresponding to ev exists, and execute it.
Definition: event_handler.h:68
Class to write data from a Gzip compressed file.
Definition: fileops.h:227
void close()
Close the file that was opened.
Definition: fileops.cc:63
#define NBR_MOVES
Total number of moves.
Definition: mapcharacter.h:106
s_int8 dir
Direction where the character is looking (-1 for any).
Definition: map_event.h:78
virtual void move(s_int16 tx, s_int16 ty)
Move the win_*.
Definition: win_base.cc:75
s_int8 put_state(ogzstream &file) const
Saves the mapcharacter&#39;s state into an opened file.
Declares the event_handler class.
To notify when a mapcharacter left a mapsquare.
Definition: map_event.h:126
void clear()
Unregisters and deletes all events owned by this list.
Definition: event_list.cc:48
#define NO_MOVE
No move.
Definition: mapcharacter.h:112
Displays neat little text speech bubbles.
Definition: text_bubble.h:46
u_int16 area_height() const
Returns the height of the area.
Class to read data from a Gzip compressed file.
Definition: fileops.h:135
void clear()
Resets the script to it&#39;s post-constructor state.
Definition: py_object.cc:46
void set_schedule_active(bool a)
Sets whether the schedule is active or not.
Definition: mapcharacter.h:652
~mapcharacter()
Destructor.
Definition: mapcharacter.cc:59
area_coord goal
Goal point.
Definition: path.h:112
s_int8 offx() const
Returns the X offset of the mapcharacter.
Definition: mapcharacter.h:566
#define u_int16
16 bits long unsigned integer
Definition: types.h:38
void detach_drawing_area()
Detach (if needed) the drawing_area which was attached to this one.
Definition: drawing_area.h:150
area_coord start
Start point.
Definition: path.h:106
u_int16 length() const
Returns the length of the drawing_area.
Definition: drawing_area.h:93
u_int16 posx() const
Returns the X position of the mapcharacter.
Definition: mapcharacter.h:544
u_int16 submap
Submap where the pathfinding will occur.
Definition: path.h:94
s_int8 put_state(ogzstream &file) const
Saves the path&#39;s state into an opened file.
Definition: path.cc:289
void set_callback(PyObject *callback, PyObject *args=NULL)
Sets a python function/method to be executed whenever the event occurs.
Definition: event.cc:118
u_int16 dir
Direction to face once the goal is reached.
Definition: path.h:100
u_int16 length() const
Returns the length of the drawable.
Definition: drawable.h:80
bool draw()
Draw process.
Definition: win_object.h:83
Class where drawables can actually be drawn to.
Definition: surface.h:85
bool go_south()
Walk to South (if possible).
Definition: str_hash.h:71
s_int8 save(string fname) const
Saves an mapcharacter into an file, in game format, with alpha and mask values.
bool update()
Update function.
Definition: text_bubble.cc:62
mapcharacter * whosnext() const
Return a pointer to the mapcharacter that is right next to this mapcharacter, i.e the mapcharacter th...
u_int16 area_length() const
Returns the length of the area.
#define WALK_SOUTH
Walking South.
Definition: mapcharacter.h:88
static void put_tuple(PyObject *tuple, ogzstream &file)
Save a Python tuple into a file.
void look_invert(u_int16 p)
Look at the opposite position of p.
void call_method(const string &name, PyObject *args=NULL) const
Call a method of this object.
Definition: py_object.h:113
#define WALK_WEST
Walking West.
Definition: mapcharacter.h:94
bool can_go_west() const
Returns whether it is possible or not to go to West from the current mapcharacter&#39;s position...
#define u_int8
8 bits long unsigned integer
Definition: types.h:35
static PyObject * instance
When restoring a callback from file, instance has to point to the python instance (module or class) c...
Definition: py_callback.h:122
To notify when a character entered a mapsquare.
Definition: map_event.h:113
#define STAND_SOUTH
Standing South.
Definition: mapcharacter.h:64
void assign_drawing_area(const drawing_area *da)
Assign a drawing_area to this drawing_area.
Definition: drawing_area.h:131
bool is_schedule_activated() const
Returns whether the schedule is activated or not.
Definition: mapcharacter.h:642
void stand_south()
Look to South.
bool get_state(igzstream &in)
Loads the event_list from a file and registers all loaded events.
Definition: event_list.cc:133
s_int16 x() const
Returns the horizontal position of the drawing_area.
Definition: drawing_area.h:77
Declares the landmap class.
void add_event(event *ev)
Adds an event to this list.
Definition: event_list.cc:62
Contains informations about the position of a character on a map.
Definition: mapsquare.h:141
#define MAPCHAR_DIR
Where mapcharacter files resides.
Definition: mapcharacter.h:37
bool update()
Updates the mapcharacter&#39;s state and launchs his schedule.
void set_action_active(bool a)
Sets whether the action is active or not.
Definition: mapcharacter.h:719
bool can_go_south() const
Returns whether it is possible or not to go to South from the current mapcharacter&#39;s position...
void remove_from_map()
Removes the mapcharacter from the landmap he was on (if any).
Base character class containing attributes and dialog stuff.
void jump_to(u_int16 smap, u_int16 x, u_int16 y, u_int16 pos=NO_MOVE)
Remove the mapcharacter from it&#39;s current place and put him to a new one.
bool create_instance(string file, string classname, PyObject *args=NULL)
Creates an instance of a Python class.
Definition: py_object.cc:57
u_int8 get_walkable() const
Gets the raw walkable parameter of a mapsquare.
landmap * refmap
Landmap where the pathfinding will occur.
Definition: path.h:88
The time event executes the attached script or callback at a certain point in game-time.
Definition: time_event.h:38
mapcharacter()
Default constructor.
Definition: mapcharacter.cc:37
static PyObject * get_tuple(igzstream &file)
Loads a Python tuple previously saved with put_tuple ().
static bool get_version(igzstream &file, u_int16 min, u_int16 max, string name)
Definition: fileops.cc:369
landmap * mymap() const
Returns a pointer to the landmap the mapcharacter is on.
Definition: mapcharacter.h:312
void run(PyObject *args=NULL)
Calls the run () method of this object.
Definition: py_object.h:125
mapcharacter * c
Pointer to the mapcharacter that can launch this event (NULL for any).
Definition: map_event.h:88
bool is_open()
Returns whether the file is opened or not.
Definition: fileops.h:103
void stand()
Stand to the current direction.
bool can_go_north() const
Returns whether it is possible or not to go to North from the current mapcharacter&#39;s position...
Implements "drawing zones" for drawing operations.
Definition: drawing_area.h:54
void stand_east()
Look to East.
#define ALL_WALKABLE
Walkable from every side.
#define WALK_NORTH
Walking North.
Definition: mapcharacter.h:82
s_int32 x
X position (-1 for any).
Definition: map_event.h:68
PyObject * get_instance(const bool &incref=true) const
Direct access to the instance object.
Definition: py_object.h:208
void clear()
Totally clears the area.
u_int16 get_move(u_int16 nbr) const
Returns the move to perform when at position nbr.
Definition: path.h:150
void stand_west()
Look to West.
u_int32 get_color() const
Returns the color representing the character.
static PyObject * pass_instance(void *instance, const char *class_name)
Magic function that makes any C object available to Python!
#define s_int16
16 bits long signed integer
Definition: types.h:47
u_int16 submap() const
Returns the index of the submap where the mapcharacter is.
Definition: mapcharacter.h:533
void clear()
Puts the mapcharacter back to it&#39;s post-constructor state.
Definition: mapcharacter.cc:67
mapsquare_walkable * get_square(u_int16 x, u_int16 y) const
Returns a pointer to a desired square.
bool is_action_activated() const
Returns whether the action is activated or not.
Definition: mapcharacter.h:709
Map where the world takes place.
Definition: landmap.h:56
s_int32 y
Y position (-1 for any).
Definition: map_event.h:73
u_int16 base_x() const
Returns the X offset of the base square of this object.
bool go_east()
Walk to East (if possible).
void set_map(landmap *m)
Puts the mapcharacter on a landmap.
Declares the time_event class.
void remove_from_pos()
Removes the mapcharacter from the place he was on the map.
const u_int16 MAPSQUARE_SIZE
Size of a mapsquare (in pixels).
#define STAND_EAST
Standing East.
Definition: mapcharacter.h:76
Representation of characters on a landmap.
Definition: mapcharacter.h:139
void callback_func0()
Calls the python function without arguments.
Definition: py_callback.cc:60
mapcharacter & operator=(const mapcharacter &m)
Mapcharacter copy (similar to copy ()).
Area of mapsquare_walkables, for use with mapcharacter and mapobject classes.
#define WALK_EAST
Walking East.
Definition: mapcharacter.h:100
#define STAND_WEST
Standing West.
Definition: mapcharacter.h:70
Declares the different map events.
s_int8 put(ogzstream &file) const
Saves an area into an opened file.
Stores the C++ <-> Python callback binding.
Definition: py_callback.h:41
u_int16 y
Y position.
Definition: path.h:81
bool go_west()
Walk to West (if possible).
s_int32 submap
Submap index (-1 for any).
Definition: map_event.h:63
#define STAND_NORTH
Standing North.
Definition: mapcharacter.h:58
Declares the win_manager class.
static void put_version(ogzstream &file, u_int16 version)
Sets the version number of a file.
Definition: fileops.cc:361
bool go_north()
Walk to North (if possible).
u_int16 nbr_moves() const
Returns the number of moves between start and goal.
Definition: path.h:138
u_int16 posy() const
Returns the Y position of the mapcharacter.
Definition: mapcharacter.h:555
Class that handles animated elements, their update and their playback.
Definition: animation.h:312
Declares the mapcharacter class.
s_int8 get(igzstream &file)
Loads an area from an opened file.
s_int8 load(string fname)
Loads a mapcharacter from it&#39;s filename.
bool do_stuff(string method, PyObject *args=NULL)
Tell the character to do something.
u_int16 base_y() const
Returns the Y offset of the base square of this object.
u_int16 currentmove() const
Returns the current move of the mapcharacter.
Definition: mapcharacter.h:588
Base class for objects that want to register events.
Definition: event_list.h:56
string action_file() const
Returns the name of the mapcharacter&#39;s current action.
Definition: mapcharacter.h:698
bool calculate()
Tries to find the shortest path possible between the start point and the goal point.
Definition: path.cc:47
void launch_action(mapcharacter *requester)
Run the mapcharacter&#39;s action, passing requester as the "requester" parameter for the action&#39;s Python...
s_int8 put(ogzstream &file) const
Saves an mapcharacter into an opened file, in game format, with alpha and mask values.
void put_state(ogzstream &out) const
Save the event_list to a file.
Definition: event_list.cc:121
#define s_int8
8 bits long signed integer
Definition: types.h:44
void stand_north()
Look to North.
void set_offset(s_int8 x, s_int8 y)
Sets the offset of the mapcharacter on it&#39;s current mapsquare.
Definition: mapcharacter.h:505
u_int16 x
X position.
Definition: path.h:75
void draw(s_int16 x, s_int16 y, const drawing_area *da_opt=NULL, surface *target=NULL) const
Draw the object on the screen.
s_int8 get_state(igzstream &file)
Restore the mapcharacter&#39;s state from an opened file.
void set_schedule(string file, PyObject *args=NULL)
Schedule control.
bool can_go_east() const
Returns whether it is possible or not to go to East from the current mapcharacter&#39;s position...
void set_action(string file, PyObject *args=NULL)
Action control.
string schedule_file() const
Returns the name of the mapcharacter&#39;s current schedule.
Definition: mapcharacter.h:631
bool has_attribute(const std::string &name)
Tests whether the object contains a certain attribute (i.e.
Definition: py_object.cc:134