Crossfire Client, Trunk
mapdata.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
19 #include "client.h"
20 
21 #include <assert.h>
22 #include <stdbool.h>
23 
24 #include "external.h"
25 #include "mapdata.h"
26 
31 
37 
39 int move_to_x = 0, move_to_y = 0;
40 bool move_to_attack = false;
41 
45 #define FOG_MAP_SIZE 512
46 
51 #define FOG_BORDER_MIN 128
52 
56 #define MAX_FACE_SIZE 16
57 
58 /* Max it can currently be. Important right now because
59  * animation has to look at everything that may be viewable,
60  * and reducing this size basically reduces processing it needs
61  * to do by 75% (64^2 vs 33^2)
62  */
63 #define CURRENT_MAX_VIEW 33
64 
78 struct BigCell {
79  struct BigCell *next;
80  struct BigCell *prev;
81 
84 
85  guint16 x, y;
86  guint8 layer;
87 };
88 
89 /* Global map rendering offsets used for local scroll prediction. */
92 int want_offset_x = 0;
93 int want_offset_y = 0;
94 
95 static void recenter_virtual_map_view(int diff_x, int diff_y);
96 static void mapdata_get_image_size(int face, guint8 *w, guint8 *h);
97 
98 static int width; //< width of current map view
99 static int height; //< height of current map view
100 
105 static struct BigCell *bigfaces_head;
106 
113 
114 static struct Map the_map;
115 
119 static void clear_cells(int x, int y, int len_y) {
120  int clear_cells_i, j;
121  memset(mapdata_cell(x, y), 0, sizeof(struct MapCell)*len_y);
122 
123  for (clear_cells_i = 0; clear_cells_i < (len_y); clear_cells_i++) {
124  struct MapCell *cell = mapdata_cell(x, y+clear_cells_i);
125  for (j=0; j < MAXLAYERS; j++) {
126  cell->heads[j].size_x = 1;
127  cell->heads[j].size_y = 1;
128  }
129  }
130 }
131 
135 inline struct MapCell *mapdata_cell(const int x, const int y) {
136  return &the_map._cells[x][y];
137 }
138 
142 bool mapdata_contains(int x, int y) {
143  if (x < 0 || y < 0 || the_map.width <= x || the_map.height <= y) {
144  return false;
145  }
146 
147  return true;
148 }
149 
150 bool mapdata_can_smooth(int x, int y, int layer) {
151  return (mapdata_cell(x, y)->heads[layer].face == 0 && layer > 0) ||
152  mapdata_cell(x, y)->smooth[layer];
153 }
154 
158 void mapdata_size(int *x, int *y) {
159  if (x != NULL) {
160  *x = the_map.width;
161  }
162 
163  if (y != NULL) {
164  *y = the_map.height;
165  }
166 }
167 
176 static void set_darkness(int x, int y, int darkness)
177 {
178  mapdata_cell(x, y)->have_darkness = 1;
179  if (mapdata_cell(x, y)->darkness == darkness) {
180  return;
181  }
182 
183  mapdata_cell(x, y)->darkness = darkness;
184  mapdata_cell(x, y)->need_update = 1;
185 }
186 
187 static void mark_resmooth(int x, int y, int layer)
188 {
189  int sdx,sdy;
190  if (mapdata_cell(x, y)->smooth[layer]>1) {
191  for (sdx=-1; sdx<2; sdx++)
192  for (sdy=-1; sdy<2; sdy++)
193  if ( (sdx || sdy) /* ignore (0,0) */
194  && ( (x+sdx >0) && (x+sdx < the_map.width) && /* only inside map */
195  (y+sdy >0) && (y+sdy < the_map.height) ) ) {
196  mapdata_cell(x+sdx, y+sdy)->need_resmooth=1;
197  }
198  }
199 }
208 static void expand_clear_face(int x, int y, int w, int h, int layer)
209 {
210  int dx, dy;
211  struct MapCell *cell;
212 
213  assert(0 <= x && x < the_map.width);
214  assert(0 <= y && y < the_map.height);
215  assert(1 <= w && w <= MAX_FACE_SIZE);
216  assert(1 <= h && h <= MAX_FACE_SIZE);
217 
218  assert(0 <= x-w+1 && x-w+1 < the_map.width);
219  assert(0 <= y-h+1 && y-h+1 < the_map.height);
220 
221  cell = mapdata_cell(x, y);
222 
223  for (dx = 0; dx < w; dx++) {
224  for (dy = !dx; dy < h; dy++) {
225  struct MapCellTailLayer *tail = &mapdata_cell(x-dx, y-dy)->tails[layer];
226  assert(0 <= x-dx && x-dx < the_map.width);
227  assert(0 <= y-dy && y-dy < the_map.height);
228  assert(0 <= layer && layer < MAXLAYERS);
229 
230  /* Do not clear faces that already have been overwritten by another
231  * face.
232  */
233  if (tail->face == cell->heads[layer].face
234  && tail->size_x == dx
235  && tail->size_y == dy) {
236  tail->face = 0;
237  tail->size_x = 0;
238  tail->size_y = 0;
239  mapdata_cell(x-dx, y-dy)->need_update = 1;
240  }
241  mark_resmooth(x-dx,y-dy,layer);
242  }
243  }
244 
245  cell->heads[layer].face = 0;
246  cell->heads[layer].animation = 0;
247  cell->heads[layer].animation_speed = 0;
248  cell->heads[layer].animation_left = 0;
249  cell->heads[layer].animation_phase = 0;
250  cell->heads[layer].size_x = 1;
251  cell->heads[layer].size_y = 1;
252  cell->need_update = 1;
253  cell->need_resmooth = 1;
254  mark_resmooth(x,y,layer);
255 }
256 
263 static void expand_clear_face_from_layer(int x, int y, int layer)
264 {
265  const struct MapCellLayer *cell;
266 
267  assert(0 <= x && x < the_map.width);
268  assert(0 <= y && y < the_map.height);
269  assert(0 <= layer && layer < MAXLAYERS);
270 
271  cell = &mapdata_cell(x, y)->heads[layer];
272  if (cell->size_x && cell->size_y) {
273  expand_clear_face(x, y, cell->size_x, cell->size_y, layer);
274  }
275 }
276 
290 static void expand_set_face(int x, int y, int layer, gint16 face, int clear)
291 {
292  struct MapCell *cell;
293  int dx, dy;
294  guint8 w, h;
295 
296  assert(0 <= x && x < the_map.width);
297  assert(0 <= y && y < the_map.height);
298  assert(0 <= layer && layer < MAXLAYERS);
299 
300  cell = mapdata_cell(x, y);
301 
302  if (clear) {
303  expand_clear_face_from_layer(x, y, layer);
304  }
305 
306  mapdata_get_image_size(face, &w, &h);
307  assert(1 <= w && w <= MAX_FACE_SIZE);
308  assert(1 <= h && h <= MAX_FACE_SIZE);
309  cell->heads[layer].face = face;
310  cell->heads[layer].size_x = w;
311  cell->heads[layer].size_y = h;
312  cell->need_update=1;
313  mark_resmooth(x,y,layer);
314 
315  for (dx = 0; dx < w; dx++) {
316  for (dy = !dx; dy < h; dy++) {
317  struct MapCellTailLayer *tail = &mapdata_cell(x-dx, y-dy)->tails[layer];
318  assert(0 <= x-dx && x-dx < the_map.width);
319  assert(0 <= y-dy && y-dy < the_map.height);
320  assert(0 <= layer && layer < MAXLAYERS);
321 
322  tail->face = face;
323  tail->size_x = dx;
324  tail->size_y = dy;
325  mapdata_cell(x-dx, y-dy)->need_update = 1;
326  mark_resmooth(x-dx,y-dy,layer);
327  }
328  }
329 }
330 
341 static void expand_clear_bigface(int x, int y, int w, int h, int layer, int set_need_update)
342 {
343  int dx, dy;
344  struct MapCellLayer *head;
345 
346  assert(0 <= x && x < MAX_VIEW);
347  assert(0 <= y && y < MAX_VIEW);
348  assert(1 <= w && w <= MAX_FACE_SIZE);
349  assert(1 <= h && h <= MAX_FACE_SIZE);
350 
351  head = &bigfaces[x][y][layer].head;
352 
353  for (dx = 0; dx < w && dx <= x; dx++) {
354  for (dy = !dx; dy < h && dy <= y; dy++) {
355  struct MapCellTailLayer *tail = &bigfaces[x-dx][y-dy][layer].tail;
356  assert(0 <= x-dx && x-dx < MAX_VIEW);
357  assert(0 <= y-dy && y-dy < MAX_VIEW);
358  assert(0 <= layer && layer < MAXLAYERS);
359 
360  /* Do not clear faces that already have been overwritten by another
361  * face.
362  */
363  if (tail->face == head->face
364  && tail->size_x == dx
365  && tail->size_y == dy) {
366  tail->face = 0;
367  tail->size_x = 0;
368  tail->size_y = 0;
369 
370  if (0 <= x-dx && x-dx < width
371  && 0 <= y-dy && y-dy < height) {
372  assert(0 <= pl_pos.x+x-dx && pl_pos.x+x-dx < the_map.width);
373  assert(0 <= pl_pos.y+y-dy && pl_pos.y+y-dy < the_map.height);
374  if (set_need_update) {
375  mapdata_cell(pl_pos.x+x-dx, pl_pos.y+y-dy)->need_update = 1;
376  }
377  }
378  }
379  }
380  }
381 
382  head->face = 0;
383  head->size_x = 1;
384  head->size_y = 1;
385 }
386 
395 static void expand_clear_bigface_from_layer(int x, int y, int layer, int set_need_update)
396 {
397  struct BigCell *headcell;
398  const struct MapCellLayer *head;
399 
400  assert(0 <= x && x < MAX_VIEW);
401  assert(0 <= y && y < MAX_VIEW);
402  assert(0 <= layer && layer < MAXLAYERS);
403 
404  headcell = &bigfaces[x][y][layer];
405  head = &headcell->head;
406  if (head->face != 0) {
407  assert(headcell->prev != NULL || headcell == bigfaces_head);
408 
409  /* remove from bigfaces_head list */
410  if (headcell->prev != NULL) {
411  headcell->prev->next = headcell->next;
412  }
413  if (headcell->next != NULL) {
414  headcell->next->prev = headcell->prev;
415  }
416  if (bigfaces_head == headcell) {
417  assert(headcell->prev == NULL);
418  bigfaces_head = headcell->next;
419  } else {
420  assert(headcell->prev != NULL);
421  }
422  headcell->prev = NULL;
423  headcell->next = NULL;
424 
425  expand_clear_bigface(x, y, head->size_x, head->size_y, layer, set_need_update);
426  } else {
427  assert(headcell->prev == NULL && headcell != bigfaces_head);
428  assert(head->size_x == 1);
429  assert(head->size_y == 1);
430  }
431 }
432 
441 static void expand_set_bigface(int x, int y, int layer, gint16 face, int clear)
442 {
443  struct BigCell *headcell;
444  struct MapCellLayer *head;
445  int dx, dy;
446  guint8 w, h;
447 
448  assert(0 <= x && x < MAX_VIEW);
449  assert(0 <= y && y < MAX_VIEW);
450  assert(0 <= layer && layer < MAXLAYERS);
451 
452  headcell = &bigfaces[x][y][layer];
453  head = &headcell->head;
454  if (clear) {
455  expand_clear_bigface_from_layer(x, y, layer, 1);
456  }
457 
458  /* add to bigfaces_head list */
459  if (face != 0) {
460  assert(headcell->prev == NULL);
461  assert(headcell->next == NULL);
462  assert(headcell != bigfaces_head);
463  if (bigfaces_head != NULL) {
464  assert(bigfaces_head->prev == NULL);
465  bigfaces_head->prev = headcell;
466  }
467  headcell->next = bigfaces_head;
468  bigfaces_head = headcell;
469  }
470 
471  mapdata_get_image_size(face, &w, &h);
472  assert(1 <= w && w <= MAX_FACE_SIZE);
473  assert(1 <= h && h <= MAX_FACE_SIZE);
474  head->face = face;
475  head->size_x = w;
476  head->size_y = h;
477 
478  for (dx = 0; dx < w && dx <= x; dx++) {
479  for (dy = !dx; dy < h && dy <= y; dy++) {
480  struct MapCellTailLayer *tail = &bigfaces[x-dx][y-dy][layer].tail;
481  assert(0 <= x-dx && x-dx < MAX_VIEW);
482  assert(0 <= y-dy && y-dy < MAX_VIEW);
483  assert(0 <= layer && layer < MAXLAYERS);
484 
485  tail->face = face;
486  tail->size_x = dx;
487  tail->size_y = dy;
488 
489  if (0 <= x-dx && x-dx < width
490  && 0 <= y-dy && y-dy < height) {
491  assert(0 <= pl_pos.x+x-dx && pl_pos.x+x-dx < the_map.width);
492  assert(0 <= pl_pos.y+y-dy && pl_pos.y+y-dy < the_map.height);
493  mapdata_cell(pl_pos.x+x-dx, pl_pos.y+y-dy)->need_update = 1;
494  }
495  }
496  }
497 }
498 
506 static void expand_need_update(int x, int y, int w, int h)
507 {
508  int dx, dy;
509 
510  assert(0 <= x && x < the_map.width);
511  assert(0 <= y && y < the_map.height);
512  assert(1 <= w && w <= MAX_FACE_SIZE);
513  assert(1 <= h && h <= MAX_FACE_SIZE);
514 
515  assert(0 <= x-w+1 && x-w+1 < the_map.width);
516  assert(0 <= y-h+1 && y-h+1 < the_map.height);
517 
518  for (dx = 0; dx < w; dx++) {
519  for (dy = 0; dy < h; dy++) {
520  struct MapCell *cell = mapdata_cell(x-dx, y-dy);
521  assert(0 <= x-dx && x-dx < the_map.width);
522  assert(0 <= y-dy && y-dy < the_map.height);
523  cell->need_update = 1;
524  }
525  }
526 }
527 
534 static void expand_need_update_from_layer(int x, int y, int layer)
535 {
536  struct MapCellLayer *head;
537 
538  assert(0 <= x && x < the_map.width);
539  assert(0 <= y && y < the_map.height);
540  assert(0 <= layer && layer < MAXLAYERS);
541 
542  head = &mapdata_cell(x, y)->heads[layer];
543  if (head->face != 0) {
544  expand_need_update(x, y, head->size_x, head->size_y);
545  } else {
546  assert(head->size_x == 1);
547  assert(head->size_y == 1);
548  }
549 }
550 
555 static void mapdata_alloc(struct Map* const map, const int width, const int height) {
556  map->_cells = (struct MapCell **)g_new(struct MapCell, width * (height + 1));
557  g_assert(map->_cells != NULL); // g_new() always succeeds
558  map->width = width;
559  map->height = height;
560 
561  /* Skip past the first row of pointers to rows and assign the
562  * start of the actual map data
563  */
564  map->_cells[0] = (struct MapCell *)((char *)map->_cells+(sizeof(struct MapCell *)*map->width));
565 
566  /* Finish assigning the beginning of each row relative to the
567  * first row assigned above
568  */
569  for (int i = 0; i < map->width; i++) {
570  map->_cells[i] = map->_cells[0]+i*map->height;
571  }
572 }
573 
574 static void mapdata_init(void)
575 {
576  int x, y;
577  int i;
578 
580 
581  width = 0;
582  height = 0;
583  pl_pos.x = the_map.width/2-width/2;
584  pl_pos.y = the_map.height/2-height/2;
585 
586  for (x = 0; x < the_map.width; x++) {
587  clear_cells(x, 0, the_map.height);
588  }
589 
590  for (y = 0; y < MAX_VIEW; y++) {
591  for (x = 0; x < MAX_VIEW; x++) {
592  for (i = 0; i < MAXLAYERS; i++) {
593  bigfaces[x][y][i].next = NULL;
594  bigfaces[x][y][i].prev = NULL;
595  bigfaces[x][y][i].head.face = 0;
596  bigfaces[x][y][i].head.size_x = 1;
597  bigfaces[x][y][i].head.size_y = 1;
598  bigfaces[x][y][i].tail.face = 0;
599  bigfaces[x][y][i].tail.size_x = 0;
600  bigfaces[x][y][i].tail.size_y = 0;
601  bigfaces[x][y][i].x = x;
602  bigfaces[x][y][i].y = y;
603  bigfaces[x][y][i].layer = i;
604  }
605  }
606  }
607  bigfaces_head = NULL;
608 
609  global_offset_x = 0;
610  global_offset_y = 0;
611  want_offset_x = 0;
612  want_offset_y = 0;
613 }
614 
615 void mapdata_free(void) {
616  if (the_map._cells != NULL) {
617  g_free(the_map._cells);
618  the_map._cells = NULL;
619  the_map.width = 0;
620  the_map.height = 0;
621  }
622 }
623 
624 void mapdata_set_size(int viewx, int viewy)
625 {
626  mapdata_free();
627  mapdata_init();
628 
629  width = viewx;
630  height = viewy;
631  pl_pos.x = the_map.width/2-width/2;
632  pl_pos.y = the_map.height/2-height/2;
633 }
634 
635 int mapdata_is_inside(int x, int y)
636 {
637  return(x >= 0 && x < width && y >= 0 && y < height);
638 }
639 
640 /* mapdate_clear_space() is used by Map2Cmd()
641  * Basically, server has told us there is nothing on
642  * this space. So clear it.
643  */
644 void mapdata_clear_space(int x, int y)
645 {
646  int px, py;
647  int i;
648 
649  assert(0 <= x && x < MAX_VIEW);
650  assert(0 <= y && y < MAX_VIEW);
651 
652  px = pl_pos.x+x;
653  py = pl_pos.y+y;
654  assert(0 <= px && px < the_map.width);
655  assert(0 <= py && py < the_map.height);
656 
657  if (x < width && y < height) {
658  /* tile is visible */
659 
660  /* visible tile is now blank ==> do not clear but mark as cleared */
661  if (!mapdata_cell(px, py)->cleared) {
662  mapdata_cell(px, py)->cleared = 1;
663  mapdata_cell(px, py)->need_update = 1;
664 
665  for (i=0; i < MAXLAYERS; i++)
666  if (mapdata_cell(px, py)->heads[i].face) {
668  }
669  }
670  } else {
671  /* tile is invisible (outside view area, i.e. big face update) */
672 
673  for (i = 0; i < MAXLAYERS; i++) {
674  expand_set_bigface(x, y, i, 0, TRUE);
675  }
676  }
677 }
678 
679 
680 /* With map2, we basically process a piece of data at a time. Thus,
681  * for each piece, we don't know what the final state of the space
682  * will be. So once Map2Cmd() has processed all the information for
683  * a space, it calls mapdata_set_check_space() which can see if
684  * the space is cleared or other inconsistencies.
685  */
686 void mapdata_set_check_space(int x, int y)
687 {
688  int px, py;
689  int is_blank;
690  int i;
691  struct MapCell *cell;
692 
693  assert(0 <= x && x < MAX_VIEW);
694  assert(0 <= y && y < MAX_VIEW);
695 
696  px = pl_pos.x+x;
697  py = pl_pos.y+y;
698 
699  assert(0 <= px && px < the_map.width);
700  assert(0 <= py && py < the_map.height);
701 
702 
703  is_blank=1;
704  cell = mapdata_cell(px, py);
705  for (i=0; i < MAXLAYERS; i++) {
706  if (cell->heads[i].face>0 || cell->tails[i].face>0) {
707  is_blank=0;
708  break;
709  }
710  }
711 
712  if (cell->have_darkness) {
713  is_blank=0;
714  }
715 
716  /* We only care if this space needs to be blanked out */
717  if (!is_blank) {
718  return;
719  }
720 
721  if (x < width && y < height) {
722  /* tile is visible */
723 
724  /* visible tile is now blank ==> do not clear but mark as cleared */
725  if (!mapdata_cell(px, py)->cleared) {
726  mapdata_cell(px, py)->cleared = 1;
727  mapdata_cell(px, py)->need_update = 1;
728 
729  for (i=0; i < MAXLAYERS; i++) {
731  }
732  }
733  }
734 }
735 
736 
737 
738 /* This just sets the darkness for a space.
739  * Used by Map2Cmd()
740  */
741 void mapdata_set_darkness(int x, int y, int darkness)
742 {
743  int px, py;
744 
745  assert(0 <= x && x < MAX_VIEW);
746  assert(0 <= y && y < MAX_VIEW);
747 
748  px = pl_pos.x+x;
749  py = pl_pos.y+y;
750  assert(0 <= px && px < the_map.width);
751  assert(0 <= py && py < the_map.height);
752 
753  /* Ignore darkness information for tile outside the viewable area: if
754  * such a tile becomes visible again, it is either "fog of war" (and
755  * darkness information is ignored) or it will be updated (including
756  * the darkness information).
757  */
758  if (darkness != -1 && x < width && y < height) {
759  set_darkness(px, py, 255-darkness);
760  }
761 }
762 
763 /* Sets smooth information for layer */
764 void mapdata_set_smooth(int x, int y, guint8 smooth, int layer)
765 {
766  static int dx[8]= {0,1,1,1,0,-1,-1,-1};
767  static int dy[8]= {-1,-1,0,1,1,1,0,-1};
768  int rx, ry, px, py, i;
769 
770  assert(0 <= x && x < MAX_VIEW);
771  assert(0 <= y && y < MAX_VIEW);
772 
773  px = pl_pos.x+x;
774  py = pl_pos.y+y;
775  assert(0 <= px && px < the_map.width);
776  assert(0 <= py && py < the_map.height);
777 
778  if (mapdata_cell(px, py)->smooth[layer] != smooth) {
779  for (i=0; i<8; i++) {
780  rx=px+dx[i];
781  ry=py+dy[i];
782  if ( (rx<0) || (ry<0) || (the_map.width<=rx) || (the_map.height<=ry)) {
783  continue;
784  }
785  mapdata_cell(rx, ry)->need_resmooth=1;
786  }
787  mapdata_cell(px, py)->need_resmooth=1;
788  mapdata_cell(px, py)->smooth[layer] = smooth;
789  }
790 }
791 
792 /* If old cell data is set and is to be cleared, clear it.
793  * This used to be in mapdata_set_face_layer(), however it needs to be
794  * called here, earlier in the Map2Cmd() because otherwise darkness
795  * doesn't work went sent before the layer data when that square was
796  * going to be cleared. This is used by the Map2Cmd()
797  */
798 void mapdata_clear_old(int x, int y)
799 {
800  int px, py;
801  int i;
802 
803  assert(0 <= x && x < MAX_VIEW);
804  assert(0 <= y && y < MAX_VIEW);
805 
806  px = pl_pos.x+x;
807  py = pl_pos.y+y;
808  assert(0 <= px && px < the_map.width);
809  assert(0 <= py && py < the_map.height);
810 
811  if (x < width && y < height)
812  if (mapdata_cell(px, py)->cleared) {
813  for (i=0; i < MAXLAYERS; i++) {
814  expand_clear_face_from_layer(px, py, i);
815  }
816 
817  mapdata_cell(px, py)->darkness = 0;
818  mapdata_cell(px, py)->have_darkness = 0;
819  }
820 }
821 
822 /* This is vaguely related to the mapdata_set_face() above, but rather
823  * than take all the faces, takes 1 face and the layer this face is
824  * on. This is used by the Map2Cmd()
825  */
826 void mapdata_set_face_layer(int x, int y, gint16 face, int layer)
827 {
828  int px, py;
829 
830  assert(0 <= x && x < MAX_VIEW);
831  assert(0 <= y && y < MAX_VIEW);
832 
833  px = pl_pos.x+x;
834  py = pl_pos.y+y;
835  assert(0 <= px && px < the_map.width);
836  assert(0 <= py && py < the_map.height);
837 
838  if (x < width && y < height) {
839  mapdata_cell(px, py)->need_update = 1;
840  if (face >0) {
841  expand_set_face(px, py, layer, face, TRUE);
842  } else {
843  expand_clear_face_from_layer(px, py, layer);
844  }
845 
846  mapdata_cell(px, py)->cleared = 0;
847  } else {
848  expand_set_bigface(x, y, layer, face, TRUE);
849  }
850 }
851 
852 
853 /* This is vaguely related to the mapdata_set_face() above, but rather
854  * than take all the faces, takes 1 face and the layer this face is
855  * on. This is used by the Map2Cmd()
856  */
857 void mapdata_set_anim_layer(int x, int y, guint16 anim, guint8 anim_speed, int layer)
858 {
859  int px, py;
860  int i, face, animation, phase, speed_left;
861 
862  assert(0 <= x && x < MAX_VIEW);
863  assert(0 <= y && y < MAX_VIEW);
864 
865  px = pl_pos.x+x;
866  py = pl_pos.y+y;
867  assert(0 <= px && px < the_map.width);
868  assert(0 <= py && py < the_map.height);
869 
870  animation = anim & ANIM_MASK;
871  face = 0;
872 
873  /* Random animation is pretty easy */
874  if ((anim & ANIM_FLAGS_MASK) == ANIM_RANDOM) {
875  const guint8 num_animations = animations[animation].num_animations;
876  if (num_animations == 0) {
877  LOG(LOG_WARNING, "mapdata_set_anim_layer",
878  "animating object with zero animations");
879  return;
880  }
881  phase = g_random_int() % num_animations;
882  face = animations[animation].faces[phase];
883  speed_left = anim_speed % g_random_int();
884  } else if ((anim & ANIM_FLAGS_MASK) == ANIM_SYNC) {
885  animations[animation].speed = anim_speed;
886  phase = animations[animation].phase;
887  speed_left = animations[animation].speed_left;
888  face = animations[animation].faces[phase];
889  }
890 
891  if (x < width && y < height) {
892  mapdata_cell(px, py)->need_update = 1;
893  if (mapdata_cell(px, py)->cleared) {
894  for (i=0; i < MAXLAYERS; i++) {
895  expand_clear_face_from_layer(px, py, i);
896  }
897 
898  mapdata_cell(px, py)->darkness = 0;
899  mapdata_cell(px, py)->have_darkness = 0;
900  }
901  if (face >0) {
902  expand_set_face(px, py, layer, face, TRUE);
903  mapdata_cell(px, py)->heads[layer].animation = animation;
904  mapdata_cell(px, py)->heads[layer].animation_phase = phase;
905  mapdata_cell(px, py)->heads[layer].animation_speed = anim_speed;
906  mapdata_cell(px, py)->heads[layer].animation_left = speed_left;
907  } else {
908  expand_clear_face_from_layer(px, py, layer);
909  }
910 
911  mapdata_cell(px, py)->cleared = 0;
912 
913  } else {
914  expand_set_bigface(x, y, layer, face, TRUE);
915  }
916 }
917 
918 
919 void mapdata_scroll(int dx, int dy)
920 {
921  script_pos.x += dx;
922  script_pos.y += dy;
923  int x, y;
924 
926 
928  struct BigCell *cell;
929 
930  /* Mark all tiles as "need_update" that are overlapped by a big face
931  * from outside the view area.
932  */
933  for (cell = bigfaces_head; cell != NULL; cell = cell->next) {
934  for (x = 0; x < cell->head.size_x; x++) {
935  for (y = !x; y < cell->head.size_y; y++) {
936  if (0 <= cell->x-x && cell->x-x < width
937  && 0 <= cell->y-y && cell->y-y < height) {
938  mapdata_cell(pl_pos.x+cell->x-x, pl_pos.y+cell->y-y)->need_update = 1;
939  }
940  }
941  }
942  }
943  } else {
944  /* Emulate map scrolling by redrawing all tiles. */
945  for (x = 0; x < width; x++) {
946  for (y = 0; y < height; y++) {
948  }
949  }
950  }
951 
952  pl_pos.x += dx;
953  pl_pos.y += dy;
954 
955  /* clear all newly visible tiles */
956  if (dx > 0) {
957  for (y = 0; y < height; y++) {
958  for (x = width-dx; x < width; x++) {
961  }
962  }
963  } else {
964  for (y = 0; y < height; y++) {
965  for (x = 0; x < -dx; x++) {
968  }
969  }
970  }
971 
972  if (dy > 0) {
973  for (x = 0; x < width; x++) {
974  for (y = height-dy; y < height; y++) {
977  }
978  }
979  } else {
980  for (x = 0; x < width; x++) {
981  for (y = 0; y < -dy; y++) {
984  }
985  }
986  }
987 
988  /* Remove all big faces outside the view area. */
989  while (bigfaces_head != NULL) {
991  }
992 
993  run_move_to();
994 }
995 
996 void mapdata_newmap(void)
997 {
998  script_pos.x = 0;
999  script_pos.y = 0;
1000  int x, y;
1001 
1002  global_offset_x = 0;
1003  global_offset_y = 0;
1004  want_offset_x = 0;
1005  want_offset_y = 0;
1006 
1007  // Clear past predictions.
1008  memset(csocket.dir, -1, sizeof(csocket.dir));
1009 
1010  /* Clear the_map.cells[]. */
1011  for (x = 0; x < the_map.width; x++) {
1012  clear_cells(x, 0, the_map.height);
1013  for (y = 0; y < the_map.height; y++) {
1014  mapdata_cell(x, y)->need_update = 1;
1015  }
1016  }
1017 
1018  /* Clear bigfaces[]. */
1019  while (bigfaces_head != NULL) {
1021  }
1022 
1023  // Clear destination.
1024  clear_move_to();
1025 }
1026 
1030 static bool mapdata_has_tile(int x, int y, int layer) {
1031  if (0 <= x && x < width && 0 <= y && y < height) {
1032  if (0 <= layer && layer < MAXLAYERS) {
1033  return true;
1034  }
1035  }
1036 
1037  return false;
1038 }
1039 
1047 gint16 mapdata_face(int x, int y, int layer) {
1048  if (!mapdata_has_tile(x, y, layer)) {
1049  return 0;
1050  }
1051 
1052  return mapdata_cell(pl_pos.x+x, pl_pos.y+y)->heads[layer].face;
1053 }
1054 
1055 gint16 mapdata_face_info(int mx, int my, int layer, int *dx, int *dy) {
1056  struct MapCellLayer *head = &mapdata_cell(mx, my)->heads[layer];
1057  struct MapCellTailLayer *tail = &mapdata_cell(mx, my)->tails[layer];
1058  if (head->face != 0) {
1059  const int width = head->size_x, height = head->size_y;
1060  *dx = 1 - width, *dy = 1 - height;
1061  return head->face;
1062  } else if (tail->face != 0) {
1063  struct MapCellLayer *head_ptr = &mapdata_cell(mx + tail->size_x, my + tail->size_y)->heads[layer];
1064  const int width = head_ptr->size_x, height = head_ptr->size_y;
1065  *dx = tail->size_x - width + 1, *dy = tail->size_y - height + 1;
1066  return tail->face;
1067  } else {
1068  return 0;
1069  }
1070 }
1071 
1081 gint16 mapdata_bigface(int x, int y, int layer, int *ww, int *hh) {
1082  gint16 result;
1083 
1084  if (!mapdata_has_tile(x, y, layer)) {
1085  return 0;
1086  }
1087 
1088  result = mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].face;
1089  if (result != 0) {
1090  int clear_bigface;
1091  int dx = mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].size_x;
1092  int dy = mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].size_y;
1093  int w = mapdata_cell(pl_pos.x+x+dx, pl_pos.y+y+dy)->heads[layer].size_x;
1094  int h = mapdata_cell(pl_pos.x+x+dx, pl_pos.y+y+dy)->heads[layer].size_y;
1095  assert(1 <= w && w <= MAX_FACE_SIZE);
1096  assert(1 <= h && h <= MAX_FACE_SIZE);
1097  assert(0 <= dx && dx < w);
1098  assert(0 <= dy && dy < h);
1099 
1100  /* Now check if we are about to display an obsolete big face: such a
1101  * face has a cleared ("fog of war") head but the current tile is not
1102  * fog of war. Since the server would have sent an appropriate head
1103  * tile if it was already valid, just clear the big face and do not
1104  * return it.
1105  */
1106  if (mapdata_cell(pl_pos.x+x, pl_pos.y+y)->cleared) {
1107  /* Current face is a "fog of war" tile ==> do not clear
1108  * old information.
1109  */
1110  clear_bigface = 0;
1111  } else {
1112  if (x+dx < width && y+dy < height) {
1113  /* Clear face if current tile is valid but the
1114  * head is marked as cleared.
1115  */
1116  clear_bigface = mapdata_cell(pl_pos.x+x+dx, pl_pos.y+y+dy)->cleared;
1117  } else {
1118  /* Clear face if current tile is valid but the
1119  * head is not set.
1120  */
1121  clear_bigface = bigfaces[x+dx][y+dy][layer].head.face == 0;
1122  }
1123  }
1124 
1125  if (!clear_bigface) {
1126  *ww = w-1-dx;
1127  *hh = h-1-dy;
1128  return(result);
1129  }
1130 
1131  assert(mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].face == result);
1132  expand_clear_face_from_layer(pl_pos.x+x+dx, pl_pos.y+y+dy, layer);
1133  assert(mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].face == 0);
1134  }
1135 
1136  result = bigfaces[x][y][layer].tail.face;
1137  if (result != 0) {
1138  int dx = bigfaces[x][y][layer].tail.size_x;
1139  int dy = bigfaces[x][y][layer].tail.size_y;
1140  int w = bigfaces[x+dx][y+dy][layer].head.size_x;
1141  int h = bigfaces[x+dx][y+dy][layer].head.size_y;
1142  assert(0 <= dx && dx < w);
1143  assert(0 <= dy && dy < h);
1144  *ww = w-1-dx;
1145  *hh = h-1-dy;
1146  return(result);
1147  }
1148 
1149  *ww = 1;
1150  *hh = 1;
1151  return(0);
1152 }
1153 
1154 /* This is used by the opengl logic.
1155  * Basically the opengl code draws the the entire image,
1156  * and doesn't care if if portions are off the edge
1157  * (opengl takes care of that). So basically, this
1158  * function returns only if the head for a space is set,
1159  * otherwise, returns 0 - we don't care about the tails
1160  * or other details really.
1161  */
1162 gint16 mapdata_bigface_head(int x, int y, int layer, int *ww, int *hh) {
1163  gint16 result;
1164 
1165  if (!mapdata_has_tile(x, y, layer)) {
1166  return 0;
1167  }
1168 
1169  result = bigfaces[x][y][layer].head.face;
1170  if (result != 0) {
1171  int w = bigfaces[x][y][layer].head.size_x;
1172  int h = bigfaces[x][y][layer].head.size_y;
1173  *ww = w;
1174  *hh = h;
1175  return(result);
1176  }
1177 
1178  *ww = 1;
1179  *hh = 1;
1180  return(0);
1181 }
1182 
1191 static void recenter_virtual_map_view(int diff_x, int diff_y)
1192 {
1193  int new_x, new_y;
1194  int shift_x, shift_y;
1195  int src_x, src_y;
1196  int dst_x, dst_y;
1197  int len_x, len_y;
1198  int sx;
1199  int dx;
1200  int i;
1201 
1202  /* shift player position in virtual map */
1203  new_x = pl_pos.x+diff_x;
1204  new_y = pl_pos.y+diff_y;
1205 
1206  /* determine neccessary amount to shift */
1207 
1208  /* if(new_x < 1) is not possible: a big face may reach up to
1209  * (MAX_FACE_SIZE-1) tiles to the left of pl_pos. Therefore maintain a
1210  * border of at least MAX_FACE_SIZE to the left of the virtual map
1211  * edge.
1212  */
1213  if (new_x < MAX_FACE_SIZE) {
1214  shift_x = FOG_BORDER_MIN+MAX_FACE_SIZE-new_x;
1215  /* This yields: new_x+shift_x == FOG_BORDER_MIN+MAX_FACE_SIZE,
1216  * i.e. left border is FOG_BORDER_MIN+MAX_FACE_SIZE after
1217  * shifting.
1218  */
1219  } else if (new_x+MAX_VIEW > the_map.width) {
1220  shift_x = the_map.width-FOG_BORDER_MIN-MAX_VIEW-new_x;
1221  /* This yields: new_x+shift_x ==
1222  * the_map.width-FOG_BODER_MIN-MAX_VIEW, i.e. right border is
1223  * FOGBORDER_MIN after shifting.
1224  */
1225  } else {
1226  shift_x = 0;
1227  }
1228 
1229  /* Same as above but for y. */
1230  if (new_y < MAX_FACE_SIZE) {
1231  shift_y = FOG_BORDER_MIN+MAX_FACE_SIZE-new_y;
1232  } else if (new_y+MAX_VIEW > the_map.height) {
1233  shift_y = the_map.height-FOG_BORDER_MIN-MAX_VIEW-new_y;
1234  } else {
1235  shift_y = 0;
1236  }
1237 
1238  /* No shift neccessary? ==> nothing to do. */
1239  if (shift_x == 0 && shift_y == 0) {
1240  return;
1241  }
1242 
1243  /* If shifting at all: maintain a border size of FOG_BORDER_MIN to all
1244  * directions. For example: if pl_pos=30/MAX_FACE_SIZE, and map_scroll is
1245  * 0/-1: shift pl_pos to FOG_BORDER_MIN+1/FOG_BORDER_MIN+1, not to
1246  * 30/FOG_BORDER_MIN+1.
1247  */
1248  if (shift_x == 0) {
1249  if (new_x < FOG_BORDER_MIN+MAX_FACE_SIZE) {
1250  shift_x = FOG_BORDER_MIN+MAX_FACE_SIZE-new_x;
1251  } else if (new_x+MAX_VIEW+FOG_BORDER_MIN > the_map.width) {
1252  shift_x = the_map.width-FOG_BORDER_MIN-MAX_VIEW-new_x;
1253  }
1254  }
1255  if (shift_y == 0) {
1256  if (new_y < FOG_BORDER_MIN+MAX_FACE_SIZE) {
1257  shift_y = FOG_BORDER_MIN+MAX_FACE_SIZE-new_y;
1258  } else if (new_y+MAX_VIEW+FOG_BORDER_MIN > the_map.height) {
1259  shift_y = the_map.height-FOG_BORDER_MIN-MAX_VIEW-new_y;
1260  }
1261  }
1262 
1263  /* Shift for more than virtual map size? ==> clear whole virtual map
1264  * and recenter.
1265  */
1266  if (shift_x <= -the_map.width || shift_x >= the_map.width
1267  || shift_y <= -the_map.height || shift_y >= the_map.height) {
1268  for (dx = 0; dx < the_map.width; dx++) {
1269  clear_cells(dx, 0, the_map.height);
1270  }
1271 
1272  pl_pos.x = the_map.width/2-width/2;
1273  pl_pos.y = the_map.height/2-height/2;
1274  return;
1275  }
1276 
1277  /* Move player position. */
1278  pl_pos.x += shift_x;
1279  pl_pos.y += shift_y;
1280 
1281  /* Actually shift the virtual map by shift_x/shift_y */
1282  if (shift_x < 0) {
1283  src_x = -shift_x;
1284  dst_x = 0;
1285  len_x = the_map.width+shift_x;
1286  } else {
1287  src_x = 0;
1288  dst_x = shift_x;
1289  len_x = the_map.width-shift_x;
1290  }
1291 
1292  if (shift_y < 0) {
1293  src_y = -shift_y;
1294  dst_y = 0;
1295  len_y = the_map.height+shift_y;
1296  } else {
1297  src_y = 0;
1298  dst_y = shift_y;
1299  len_y = the_map.height-shift_y;
1300  }
1301 
1302  if (shift_x < 0) {
1303  for (sx = src_x, dx = dst_x, i = 0; i < len_x; sx++, dx++, i++) {
1304  /* srcx!=dstx ==> can use memcpy since source and
1305  * destination to not overlap.
1306  */
1307  memcpy(mapdata_cell(dx, dst_y), mapdata_cell(sx, src_y), len_y*sizeof(struct MapCell));
1308  }
1309  } else if (shift_x > 0) {
1310  for (sx = src_x+len_x-1, dx = dst_x+len_x-1, i = 0; i < len_x; sx--, dx--, i++) {
1311  /* srcx!=dstx ==> can use memcpy since source and
1312  * destination to not overlap.
1313  */
1314  memcpy(mapdata_cell(dx, dst_y), mapdata_cell(sx, src_y), len_y*sizeof(struct MapCell));
1315  }
1316  } else {
1317  assert(src_x == dst_x);
1318  for (dx = src_x, i = 0; i < len_x; dx++, i++) {
1319  /* srcx==dstx ==> use memmove since source and
1320  * destination probably do overlap.
1321  */
1322  memmove(mapdata_cell(dx, dst_y), mapdata_cell(dx, src_y), len_y*sizeof(struct MapCell));
1323  }
1324  }
1325 
1326  /* Clear newly opened area */
1327  for (dx = 0; dx < dst_x; dx++) {
1328  clear_cells(dx, 0, the_map.height);
1329  }
1330  for (dx = dst_x+len_x; dx < the_map.width; dx++) {
1331  clear_cells(dx, 0, the_map.height);
1332  }
1333  if (shift_y > 0) {
1334  for (dx = 0; dx < len_x; dx++) {
1335  clear_cells(dx+dst_x, 0, shift_y);
1336  }
1337  } else if (shift_y < 0) {
1338  for (dx = 0; dx < len_x; dx++) {
1339  clear_cells(dx+dst_x, the_map.height+shift_y, -shift_y);
1340  }
1341  }
1342 }
1343 
1348 static void mapdata_get_image_size(int face, guint8 *w, guint8 *h)
1349 {
1350  get_map_image_size(face, w, h);
1351  if (*w < 1) {
1352  *w = 1;
1353  }
1354  if (*h < 1) {
1355  *h = 1;
1356  }
1357  if (*w > MAX_FACE_SIZE) {
1358  *w = MAX_FACE_SIZE;
1359  }
1360  if (*h > MAX_FACE_SIZE) {
1361  *h = MAX_FACE_SIZE;
1362  }
1363 }
1364 
1365 /* This basically goes through all the map spaces and does the necessary
1366  * animation.
1367  */
1369 {
1370  int x, y, layer, face;
1371  struct MapCellLayer *cell;
1372 
1373 
1374  /* For synchronized animations, what we do is set the initial values
1375  * in the mapdata to the fields in the animations[] array. In this way,
1376  * the code below the iterates the spaces doesn't need to do anything
1377  * special. But we have to update the animations[] array here to
1378  * keep in sync.
1379  */
1380  for (x=0; x < MAXANIM; x++) {
1381  if (animations[x].speed) {
1382  animations[x].speed_left++;
1383  if (animations[x].speed_left >= animations[x].speed) {
1384  animations[x].speed_left=0;
1385  animations[x].phase++;
1386  if (animations[x].phase >= animations[x].num_animations) {
1387  animations[x].phase=0;
1388  }
1389  }
1390  }
1391  }
1392 
1393  for (x=0; x < CURRENT_MAX_VIEW; x++) {
1394  for (y=0; y < CURRENT_MAX_VIEW; y++) {
1395  struct MapCell *map_space = mapdata_cell(pl_pos.x + x, pl_pos.y + y);
1396 
1397  /* Short cut some processing here. It makes sense to me
1398  * not to animate stuff out of view
1399  */
1400  if (map_space->cleared) {
1401  continue;
1402  }
1403 
1404  for (layer=0; layer<MAXLAYERS; layer++) {
1405  /* Using the cell structure just makes life easier here */
1406  cell = &map_space->heads[layer];
1407 
1408  if (cell->animation) {
1409  cell->animation_left++;
1410  if (cell->animation_left >= cell->animation_speed) {
1411  cell->animation_left=0;
1412  cell->animation_phase++;
1413  if (cell->animation_phase >= animations[cell->animation].num_animations) {
1414  cell->animation_phase=0;
1415  }
1416  face = animations[cell->animation].faces[cell->animation_phase];
1417 
1418  /* I don't think we send any to the client, but it is possible
1419  * for animations to have blank faces.
1420  */
1421  if (face >0) {
1422  expand_set_face(pl_pos.x + x, pl_pos.y + y, layer, face, FALSE);
1423  } else {
1424  expand_clear_face_from_layer(pl_pos.x + x, pl_pos.y + y , layer);
1425  }
1426  }
1427  }
1428  cell = &bigfaces[x][y][layer].head;
1429  if (cell->animation) {
1430  cell->animation_left++;
1431  if (cell->animation_left >= cell->animation_speed) {
1432  cell->animation_left=0;
1433  cell->animation_phase++;
1434  if (cell->animation_phase >= animations[cell->animation].num_animations) {
1435  cell->animation_phase=0;
1436  }
1437  face = animations[cell->animation].faces[cell->animation_phase];
1438 
1439  /* I don't think we send any to the client, but it is possible
1440  * for animations to have blank faces.
1441  */
1442  expand_set_bigface(x, y, layer, face, FALSE);
1443  }
1444  }
1445  }
1446  }
1447  }
1448 }
1449 
1455 void pl_mpos(int *px, int *py) {
1456  const int vw = use_config[CONFIG_MAPWIDTH];
1457  const int vh = use_config[CONFIG_MAPHEIGHT];
1458  *px = pl_pos.x + vw/2;
1459  *py = pl_pos.y + vh/2;
1460 }
1461 
1462 void set_move_to(int dx, int dy) {
1463  int old_move_to_x = move_to_x;
1464  int old_move_to_y = move_to_y;
1465 
1467  move_to_x += dx;
1468  move_to_y += dy;
1469 
1470  if (move_to_x == old_move_to_x && move_to_y == old_move_to_y) {
1471  // Detect double-click.
1472  move_to_attack = true;
1473  } else {
1474  move_to_attack = false;
1475  }
1476 }
1477 
1479  move_to_x = 0;
1480  move_to_y = 0;
1481  move_to_attack = false;
1482 }
1483 
1485  if (move_to_x == 0 && move_to_y == 0) {
1486  return true;
1487  }
1488 
1489  int px, py;
1490  pl_mpos(&px, &py);
1491  return !(move_to_x != px || move_to_y != py);
1492 }
1493 
1494 void run_move_to() {
1495  if (move_to_x == 0 && move_to_y == 0) {
1496  // If not moving to a tile, skip to avoid calling stop_run().
1497  return;
1498  }
1499 
1500  if (is_at_moveto()) {
1501  clear_move_to();
1502  stop_run();
1503  return;
1504  }
1505 
1506  int px, py;
1507  pl_mpos(&px, &py);
1508  int dx = move_to_x - px;
1509  int dy = move_to_y - py;
1510  int dir = relative_direction(dx, dy);
1511 
1512  if (move_to_attack) {
1513  run_dir(dir);
1514  } else {
1515  walk_dir(dir);
1516  }
1517 }
run_dir
void run_dir(int dir)
Definition: player.c:150
mapdata_cell
struct MapCell * mapdata_cell(const int x, const int y)
Definition: mapdata.c:135
Map::height
int height
Definition: mapdata.h:71
ANIM_SYNC
#define ANIM_SYNC
Definition: newclient.h:318
MapCellTailLayer::size_x
gint8 size_x
Definition: mapdata.h:38
mapdata_clear_space
void mapdata_clear_space(int x, int y)
Definition: mapdata.c:644
relative_direction
int relative_direction(int dx, int dy)
Definition: map.c:511
LOG_WARNING
@ LOG_WARNING
Warning that something might not work.
Definition: client.h:435
Map
Definition: mapdata.h:67
PlayerPosition::x
int x
Definition: client.h:525
is_at_moveto
bool is_at_moveto()
Definition: mapdata.c:1484
want_offset_x
int want_offset_x
Definition: mapdata.c:92
MapCell::cleared
guint8 cleared
Definition: mapdata.h:64
mapdata_bigface
gint16 mapdata_bigface(int x, int y, int layer, int *ww, int *hh)
Definition: mapdata.c:1081
external.h
mapdata_set_face_layer
void mapdata_set_face_layer(int x, int y, gint16 face, int layer)
Definition: mapdata.c:826
Animations::phase
guint8 phase
Definition: client.h:107
move_to_x
int move_to_x
Definition: mapdata.c:39
mapdata_newmap
void mapdata_newmap(void)
Definition: mapdata.c:996
mapdata_face
gint16 mapdata_face(int x, int y, int layer)
Definition: mapdata.c:1047
BigCell::head
struct MapCellLayer head
Definition: mapdata.c:82
expand_need_update
static void expand_need_update(int x, int y, int w, int h)
Definition: mapdata.c:506
Animations::num_animations
guint8 num_animations
Definition: client.h:101
height
static int height
Definition: mapdata.c:99
mapdata_set_smooth
void mapdata_set_smooth(int x, int y, guint8 smooth, int layer)
Definition: mapdata.c:764
bigfaces_head
static struct BigCell * bigfaces_head
Definition: mapdata.c:105
mapdata_set_check_space
void mapdata_set_check_space(int x, int y)
Definition: mapdata.c:686
mapdata_can_smooth
bool mapdata_can_smooth(int x, int y, int layer)
Definition: mapdata.c:150
move_to_attack
bool move_to_attack
Definition: mapdata.c:40
MapCellTailLayer::face
gint16 face
Definition: mapdata.h:37
expand_clear_face
static void expand_clear_face(int x, int y, int w, int h, int layer)
Definition: mapdata.c:208
Animations::speed
guint8 speed
Definition: client.h:105
FOG_MAP_SIZE
#define FOG_MAP_SIZE
Definition: mapdata.c:45
mapdata_alloc
static void mapdata_alloc(struct Map *const map, const int width, const int height)
Definition: mapdata.c:555
mapdata_clear_old
void mapdata_clear_old(int x, int y)
Definition: mapdata.c:798
expand_need_update_from_layer
static void expand_need_update_from_layer(int x, int y, int layer)
Definition: mapdata.c:534
PlayerPosition::y
int y
Definition: client.h:526
display_mapscroll
int display_mapscroll(int dx, int dy)
Definition: map.c:156
FOG_BORDER_MIN
#define FOG_BORDER_MIN
Definition: mapdata.c:51
mapdata.h
global_offset_y
int global_offset_y
Definition: mapdata.c:91
expand_set_bigface
static void expand_set_bigface(int x, int y, int layer, gint16 face, int clear)
Definition: mapdata.c:441
mapdata_init
static void mapdata_init(void)
Definition: mapdata.c:574
MapCellLayer::face
gint16 face
Definition: mapdata.h:19
recenter_virtual_map_view
static void recenter_virtual_map_view(int diff_x, int diff_y)
Definition: mapdata.c:1191
MapCellTailLayer::size_y
gint8 size_y
Definition: mapdata.h:39
MapCell::heads
struct MapCellLayer heads[MAXLAYERS]
Definition: mapdata.h:57
mapdata_get_image_size
static void mapdata_get_image_size(int face, guint8 *w, guint8 *h)
Definition: mapdata.c:1348
mapdata_size
void mapdata_size(int *x, int *y)
Definition: mapdata.c:158
ANIM_RANDOM
#define ANIM_RANDOM
Definition: newclient.h:317
move_to_y
int move_to_y
Definition: mapdata.c:39
mapdata_free
void mapdata_free(void)
Definition: mapdata.c:615
MapCellLayer::animation_phase
guint8 animation_phase
Definition: mapdata.h:33
CONFIG_MAPSCROLL
#define CONFIG_MAPSCROLL
Definition: client.h:211
mapdata_has_tile
static bool mapdata_has_tile(int x, int y, int layer)
Definition: mapdata.c:1030
mapdata_set_anim_layer
void mapdata_set_anim_layer(int x, int y, guint16 anim, guint8 anim_speed, int layer)
Definition: mapdata.c:857
Map::_cells
struct MapCell ** _cells
Definition: mapdata.h:69
want_offset_y
int want_offset_y
Definition: mapdata.c:93
MapCell::smooth
guint8 smooth[MAXLAYERS]
Definition: mapdata.h:59
LOG
void LOG(LogLevel level, const char *origin, const char *format,...)
Definition: misc.c:111
global_offset_x
int global_offset_x
Definition: mapdata.c:90
mapdata_bigface_head
gint16 mapdata_bigface_head(int x, int y, int layer, int *ww, int *hh)
Definition: mapdata.c:1162
width
static int width
Definition: mapdata.c:98
walk_dir
void walk_dir(int dir)
Definition: player.c:177
the_map
static struct Map the_map
Definition: mapdata.c:114
want_config
gint16 want_config[CONFIG_NUMS]
Definition: init.c:41
csocket
ClientSocket csocket
Definition: client.c:70
MapCell::darkness
guint8 darkness
Definition: mapdata.h:60
expand_clear_bigface_from_layer
static void expand_clear_bigface_from_layer(int x, int y, int layer, int set_need_update)
Definition: mapdata.c:395
mapdata_face_info
gint16 mapdata_face_info(int mx, int my, int layer, int *dx, int *dy)
Definition: mapdata.c:1055
MapCell
Definition: mapdata.h:55
Map::width
int width
Definition: mapdata.h:70
mark_resmooth
static void mark_resmooth(int x, int y, int layer)
Definition: mapdata.c:187
Animations::speed_left
guint8 speed_left
Definition: client.h:106
BigCell::next
struct BigCell * next
Definition: mapdata.c:79
MapCell::have_darkness
guint8 have_darkness
Definition: mapdata.h:62
get_map_image_size
void get_map_image_size(int face, guint8 *w, guint8 *h)
Definition: image.c:341
mapdata_is_inside
int mapdata_is_inside(int x, int y)
Definition: mapdata.c:635
stop_run
void stop_run()
Definition: player.c:145
mapdata_contains
bool mapdata_contains(int x, int y)
Definition: mapdata.c:142
expand_clear_bigface
static void expand_clear_bigface(int x, int y, int w, int h, int layer, int set_need_update)
Definition: mapdata.c:341
MapCell::need_resmooth
guint8 need_resmooth
Definition: mapdata.h:63
map
static item * map
Definition: item.c:27
MapCellTailLayer
Definition: mapdata.h:36
set_move_to
void set_move_to(int dx, int dy)
Definition: mapdata.c:1462
Animations::faces
guint16 * faces
Definition: client.h:108
MapCell::tails
struct MapCellTailLayer tails[MAXLAYERS]
Definition: mapdata.h:58
MAX_FACE_SIZE
#define MAX_FACE_SIZE
Definition: mapdata.c:56
set_darkness
static void set_darkness(int x, int y, int darkness)
Definition: mapdata.c:176
bigfaces
static struct BigCell bigfaces[MAX_VIEW][MAX_VIEW][MAXLAYERS]
Definition: mapdata.c:112
MapCellLayer
Definition: mapdata.h:18
CONFIG_MAPWIDTH
#define CONFIG_MAPWIDTH
Definition: client.h:201
mapdata_scroll
void mapdata_scroll(int dx, int dy)
Definition: mapdata.c:919
BigCell::layer
guint8 layer
Definition: mapdata.c:86
clear_move_to
void clear_move_to()
Definition: mapdata.c:1478
ANIM_MASK
#define ANIM_MASK
Definition: newclient.h:326
MapCellLayer::size_x
gint8 size_x
Definition: mapdata.h:20
mapdata_set_size
void mapdata_set_size(int viewx, int viewy)
Definition: mapdata.c:624
expand_clear_face_from_layer
static void expand_clear_face_from_layer(int x, int y, int layer)
Definition: mapdata.c:263
BigCell::x
guint16 x
Definition: mapdata.c:85
pl_mpos
void pl_mpos(int *px, int *py)
Definition: mapdata.c:1455
MapCellLayer::animation_left
guint8 animation_left
Definition: mapdata.h:32
MapCellLayer::size_y
gint8 size_y
Definition: mapdata.h:21
PlayerPosition
Definition: client.h:524
CURRENT_MAX_VIEW
#define CURRENT_MAX_VIEW
Definition: mapdata.c:63
mapdata_set_darkness
void mapdata_set_darkness(int x, int y, int darkness)
Definition: mapdata.c:741
use_config
gint16 use_config[CONFIG_NUMS]
Definition: client.h:242
ClientSocket::dir
gint8 dir[COMMAND_MAX]
Definition: client.h:136
MAXLAYERS
#define MAXLAYERS
Definition: mapdata.h:6
pl_pos
PlayerPosition pl_pos
Definition: mapdata.c:30
run_move_to
void run_move_to()
Definition: mapdata.c:1494
MAXANIM
#define MAXANIM
Definition: client.h:86
animations
Animations animations[MAXANIM]
Definition: commands.c:1155
ANIM_FLAGS_MASK
#define ANIM_FLAGS_MASK
Definition: newclient.h:320
clear_cells
static void clear_cells(int x, int y, int len_y)
Definition: mapdata.c:119
CONFIG_MAPHEIGHT
#define CONFIG_MAPHEIGHT
Definition: client.h:202
expand_set_face
static void expand_set_face(int x, int y, int layer, gint16 face, int clear)
Definition: mapdata.c:290
BigCell
Definition: mapdata.c:78
MAX_VIEW
#define MAX_VIEW
Definition: mapdata.h:11
BigCell::tail
struct MapCellTailLayer tail
Definition: mapdata.c:83
mapdata_animation
void mapdata_animation(void)
Definition: mapdata.c:1368
BigCell::y
guint16 y
Definition: mapdata.c:85
MapCellLayer::animation_speed
guint8 animation_speed
Definition: mapdata.h:31
BigCell::prev
struct BigCell * prev
Definition: mapdata.c:80
MapCell::need_update
guint8 need_update
Definition: mapdata.h:61
client.h
MapCellLayer::animation
gint16 animation
Definition: mapdata.h:30
script_pos
PlayerPosition script_pos
Definition: mapdata.c:36