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