Crossfire Client, Trunk  R20507
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 
30 #define FOG_MAP_SIZE 512
31 
36 #define FOG_BORDER_MIN 128
37 
41 #define MAX_FACE_SIZE 16
42 
43 /* Max it can currently be. Important right now because
44  * animation has to look at everything that may be viewable,
45  * and reducing this size basically reduces processing it needs
46  * to do by 75% (64^2 vs 33^2)
47  */
48 #define CURRENT_MAX_VIEW 33
49 
63 struct BigCell {
64  struct BigCell *next;
65  struct BigCell *prev;
66 
69 
70  guint16 x, y;
71  guint8 layer;
72 };
73 
74 
75 static void recenter_virtual_map_view(int diff_x, int diff_y);
76 static void mapdata_get_image_size(int face, guint8 *w, guint8 *h);
77 
78 
82 static int width, height;
83 
84 
89 static struct BigCell *bigfaces_head;
90 
97 
98 
99 struct Map the_map;
100 
104 static void clear_cells(int x, int y, int len_y) {
105  int clear_cells_i, j;
106  memset(&the_map.cells[(x)][(y)], 0, sizeof(the_map.cells[(x)][(y)])*(len_y));
107 
108  for (clear_cells_i = 0; clear_cells_i < (len_y); clear_cells_i++) {
109  for (j=0; j < MAXLAYERS; j++) {
110  the_map.cells[(x)][(y)+clear_cells_i].heads[j].size_x = 1;
111  the_map.cells[(x)][(y)+clear_cells_i].heads[j].size_y = 1;
112  }
113  }
114 }
115 
119 struct MapCell *mapdata_cell(int x, int y) {
120  return &the_map.cells[x][y];
121 }
122 
126 bool mapdata_contains(int x, int y) {
127  if (x < 0 || y < 0 || the_map.x <= x || the_map.y <= y) {
128  return false;
129  }
130 
131  return true;
132 }
133 
134 bool mapdata_can_smooth(int x, int y, int layer) {
135  return (mapdata_cell(x, y)->heads[layer].face == 0 && layer > 0) ||
136  mapdata_cell(x, y)->smooth[layer];
137 }
138 
142 void mapdata_size(int *x, int *y) {
143  if (x != NULL) {
144  *x = the_map.x;
145  }
146 
147  if (y != NULL) {
148  *y = the_map.y;
149  }
150 }
151 
160 static void set_darkness(int x, int y, int darkness)
161 {
162  mapdata_cell(x, y)->have_darkness = 1;
163  if (mapdata_cell(x, y)->darkness == darkness) {
164  return;
165  }
166 
167  mapdata_cell(x, y)->darkness = darkness;
168  mapdata_cell(x, y)->need_update = 1;
169 
170  /* pretty ugly - since the light code with pngximage uses neighboring
171  * spaces to adjust the darkness, we now need to let the neighbors know
172  * they should update their darkness now.
173  */
177  if (x > 1) {
178  the_map.cells[x-1][y].need_update = 1;
179  }
180  if (y > 1) {
181  the_map.cells[x][y-1].need_update = 1;
182  }
183  if (x < width-1) {
184  the_map.cells[x+1][y].need_update = 1;
185  }
186  if (y < height-1) {
187  the_map.cells[x][y+1].need_update = 1;
188  }
189  }
190 }
191 
192 static void mark_resmooth(int x, int y, int layer)
193 {
194  int sdx,sdy;
195  if (mapdata_cell(x, y)->smooth[layer]>1) {
196  for (sdx=-1; sdx<2; sdx++)
197  for (sdy=-1; sdy<2; sdy++)
198  if ( (sdx || sdy) /* ignore (0,0) */
199  && ( (x+sdx >0) && (x+sdx < FOG_MAP_SIZE) && /* only inside map */
200  (y+sdy >0) && (y+sdy < FOG_MAP_SIZE) ) ) {
201  the_map.cells[x+sdx][y+sdy].need_resmooth=1;
202  }
203  }
204 }
213 static void expand_clear_face(int x, int y, int w, int h, int layer)
214 {
215  int dx, dy;
216  struct MapCell *cell;
217 
218  assert(0 <= x && x < FOG_MAP_SIZE);
219  assert(0 <= y && y < FOG_MAP_SIZE);
220  assert(1 <= w && w <= MAX_FACE_SIZE);
221  assert(1 <= h && h <= MAX_FACE_SIZE);
222 
223  assert(0 <= x-w+1 && x-w+1 < FOG_MAP_SIZE);
224  assert(0 <= y-h+1 && y-h+1 < FOG_MAP_SIZE);
225 
226  cell = mapdata_cell(x, y);
227 
228  for (dx = 0; dx < w; dx++) {
229  for (dy = !dx; dy < h; dy++) {
230  struct MapCellLayer *tail = &the_map.cells[x-dx][y-dy].tails[layer];
231  assert(0 <= x-dx && x-dx < FOG_MAP_SIZE);
232  assert(0 <= y-dy && y-dy < FOG_MAP_SIZE);
233  assert(0 <= layer && layer < MAXLAYERS);
234 
235  /* Do not clear faces that already have been overwritten by another
236  * face.
237  */
238  if (tail->face == cell->heads[layer].face
239  && tail->size_x == dx
240  && tail->size_y == dy) {
241  tail->face = 0;
242  tail->size_x = 0;
243  tail->size_y = 0;
244  the_map.cells[x-dx][y-dy].need_update = 1;
245  }
246  mark_resmooth(x-dx,y-dy,layer);
247  }
248  }
249 
250  cell->heads[layer].face = 0;
251  cell->heads[layer].animation = 0;
252  cell->heads[layer].animation_speed = 0;
253  cell->heads[layer].animation_left = 0;
254  cell->heads[layer].animation_phase = 0;
255  cell->heads[layer].size_x = 1;
256  cell->heads[layer].size_y = 1;
257  cell->need_update = 1;
258  cell->need_resmooth = 1;
259  mark_resmooth(x,y,layer);
260 }
261 
268 static void expand_clear_face_from_layer(int x, int y, int layer)
269 {
270  const struct MapCellLayer *cell;
271 
272  assert(0 <= x && x < FOG_MAP_SIZE);
273  assert(0 <= y && y < FOG_MAP_SIZE);
274  assert(0 <= layer && layer < MAXLAYERS);
275 
276  cell = &mapdata_cell(x, y)->heads[layer];
277  if (cell->size_x && cell->size_y) {
278  expand_clear_face(x, y, cell->size_x, cell->size_y, layer);
279  }
280 }
281 
295 static void expand_set_face(int x, int y, int layer, gint16 face, int clear)
296 {
297  struct MapCell *cell;
298  int dx, dy;
299  guint8 w, h;
300 
301  assert(0 <= x && x < FOG_MAP_SIZE);
302  assert(0 <= y && y < FOG_MAP_SIZE);
303  assert(0 <= layer && layer < MAXLAYERS);
304 
305  cell = mapdata_cell(x, y);
306 
307  if (clear) {
308  expand_clear_face_from_layer(x, y, layer);
309  }
310 
311  mapdata_get_image_size(face, &w, &h);
312  assert(1 <= w && w <= MAX_FACE_SIZE);
313  assert(1 <= h && h <= MAX_FACE_SIZE);
314  cell->heads[layer].face = face;
315  cell->heads[layer].size_x = w;
316  cell->heads[layer].size_y = h;
317  cell->need_update=1;
318  mark_resmooth(x,y,layer);
319 
320  for (dx = 0; dx < w; dx++) {
321  for (dy = !dx; dy < h; dy++) {
322  struct MapCellLayer *tail = &the_map.cells[x-dx][y-dy].tails[layer];
323  assert(0 <= x-dx && x-dx < FOG_MAP_SIZE);
324  assert(0 <= y-dy && y-dy < FOG_MAP_SIZE);
325  assert(0 <= layer && layer < MAXLAYERS);
326 
327  tail->face = face;
328  tail->size_x = dx;
329  tail->size_y = dy;
330  the_map.cells[x-dx][y-dy].need_update = 1;
331  mark_resmooth(x-dx,y-dy,layer);
332  }
333  }
334 }
335 
346 static void expand_clear_bigface(int x, int y, int w, int h, int layer, int set_need_update)
347 {
348  int dx, dy;
349  struct MapCellLayer *head;
350 
351  assert(0 <= x && x < MAX_VIEW);
352  assert(0 <= y && y < MAX_VIEW);
353  assert(1 <= w && w <= MAX_FACE_SIZE);
354  assert(1 <= h && h <= MAX_FACE_SIZE);
355 
356  head = &bigfaces[x][y][layer].head;
357 
358  for (dx = 0; dx < w && dx <= x; dx++) {
359  for (dy = !dx; dy < h && dy <= y; dy++) {
360  struct MapCellLayer *tail = &bigfaces[x-dx][y-dy][layer].tail;
361  assert(0 <= x-dx && x-dx < MAX_VIEW);
362  assert(0 <= y-dy && y-dy < MAX_VIEW);
363  assert(0 <= layer && layer < MAXLAYERS);
364 
365  /* Do not clear faces that already have been overwritten by another
366  * face.
367  */
368  if (tail->face == head->face
369  && tail->size_x == dx
370  && tail->size_y == dy) {
371  tail->face = 0;
372  tail->size_x = 0;
373  tail->size_y = 0;
374 
375  if (0 <= x-dx && x-dx < width
376  && 0 <= y-dy && y-dy < height) {
377  assert(0 <= pl_pos.x+x-dx && pl_pos.x+x-dx < FOG_MAP_SIZE);
378  assert(0 <= pl_pos.y+y-dy && pl_pos.y+y-dy < FOG_MAP_SIZE);
379  if (set_need_update) {
380  the_map.cells[pl_pos.x+x-dx][pl_pos.y+y-dy].need_update = 1;
381  }
382  }
383  }
384  }
385  }
386 
387  head->face = 0;
388  head->size_x = 1;
389  head->size_y = 1;
390 }
391 
400 static void expand_clear_bigface_from_layer(int x, int y, int layer, int set_need_update)
401 {
402  struct BigCell *headcell;
403  const struct MapCellLayer *head;
404 
405  assert(0 <= x && x < MAX_VIEW);
406  assert(0 <= y && y < MAX_VIEW);
407  assert(0 <= layer && layer < MAXLAYERS);
408 
409  headcell = &bigfaces[x][y][layer];
410  head = &headcell->head;
411  if (head->face != 0) {
412  assert(headcell->prev != NULL || headcell == bigfaces_head);
413 
414  /* remove from bigfaces_head list */
415  if (headcell->prev != NULL) {
416  headcell->prev->next = headcell->next;
417  }
418  if (headcell->next != NULL) {
419  headcell->next->prev = headcell->prev;
420  }
421  if (bigfaces_head == headcell) {
422  assert(headcell->prev == NULL);
423  bigfaces_head = headcell->next;
424  } else {
425  assert(headcell->prev != NULL);
426  }
427  headcell->prev = NULL;
428  headcell->next = NULL;
429 
430  expand_clear_bigface(x, y, head->size_x, head->size_y, layer, set_need_update);
431  } else {
432  assert(headcell->prev == NULL && headcell != bigfaces_head);
433  assert(head->size_x == 1);
434  assert(head->size_y == 1);
435  }
436 }
437 
446 static void expand_set_bigface(int x, int y, int layer, gint16 face, int clear)
447 {
448  struct BigCell *headcell;
449  struct MapCellLayer *head;
450  int dx, dy;
451  guint8 w, h;
452 
453  assert(0 <= x && x < MAX_VIEW);
454  assert(0 <= y && y < MAX_VIEW);
455  assert(0 <= layer && layer < MAXLAYERS);
456 
457  headcell = &bigfaces[x][y][layer];
458  head = &headcell->head;
459  if (clear) {
460  expand_clear_bigface_from_layer(x, y, layer, 1);
461  }
462 
463  /* add to bigfaces_head list */
464  if (face != 0) {
465  assert(headcell->prev == NULL);
466  assert(headcell->next == NULL);
467  assert(headcell != bigfaces_head);
468  if (bigfaces_head != NULL) {
469  assert(bigfaces_head->prev == NULL);
470  bigfaces_head->prev = headcell;
471  }
472  headcell->next = bigfaces_head;
473  bigfaces_head = headcell;
474  }
475 
476  mapdata_get_image_size(face, &w, &h);
477  assert(1 <= w && w <= MAX_FACE_SIZE);
478  assert(1 <= h && h <= MAX_FACE_SIZE);
479  head->face = face;
480  head->size_x = w;
481  head->size_y = h;
482 
483  for (dx = 0; dx < w && dx <= x; dx++) {
484  for (dy = !dx; dy < h && dy <= y; dy++) {
485  struct MapCellLayer *tail = &bigfaces[x-dx][y-dy][layer].tail;
486  assert(0 <= x-dx && x-dx < MAX_VIEW);
487  assert(0 <= y-dy && y-dy < MAX_VIEW);
488  assert(0 <= layer && layer < MAXLAYERS);
489 
490  tail->face = face;
491  tail->size_x = dx;
492  tail->size_y = dy;
493 
494  if (0 <= x-dx && x-dx < width
495  && 0 <= y-dy && y-dy < height) {
496  assert(0 <= pl_pos.x+x-dx && pl_pos.x+x-dx < FOG_MAP_SIZE);
497  assert(0 <= pl_pos.y+y-dy && pl_pos.y+y-dy < FOG_MAP_SIZE);
498  the_map.cells[pl_pos.x+x-dx][pl_pos.y+y-dy].need_update = 1;
499  }
500  }
501  }
502 }
503 
511 static void expand_need_update(int x, int y, int w, int h)
512 {
513  int dx, dy;
514 
515  assert(0 <= x && x < FOG_MAP_SIZE);
516  assert(0 <= y && y < FOG_MAP_SIZE);
517  assert(1 <= w && w <= MAX_FACE_SIZE);
518  assert(1 <= h && h <= MAX_FACE_SIZE);
519 
520  assert(0 <= x-w+1 && x-w+1 < FOG_MAP_SIZE);
521  assert(0 <= y-h+1 && y-h+1 < FOG_MAP_SIZE);
522 
523  for (dx = 0; dx < w; dx++) {
524  for (dy = 0; dy < h; dy++) {
525  struct MapCell *cell = &the_map.cells[x-dx][y-dy];
526  assert(0 <= x-dx && x-dx < FOG_MAP_SIZE);
527  assert(0 <= y-dy && y-dy < FOG_MAP_SIZE);
528  cell->need_update = 1;
529  }
530  }
531 }
532 
539 static void expand_need_update_from_layer(int x, int y, int layer)
540 {
541  struct MapCellLayer *head;
542 
543  assert(0 <= x && x < FOG_MAP_SIZE);
544  assert(0 <= y && y < FOG_MAP_SIZE);
545  assert(0 <= layer && layer < MAXLAYERS);
546 
547  head = &mapdata_cell(x, y)->heads[layer];
548  if (head->face != 0) {
549  expand_need_update(x, y, head->size_x, head->size_y);
550  } else {
551  assert(head->size_x == 1);
552  assert(head->size_y == 1);
553  }
554 }
555 
556 void mapdata_init(void)
557 {
558  int x, y;
559  int i;
560 
561  if (the_map.cells == NULL) {
562  the_map.cells = g_malloc(
563  sizeof(*the_map.cells)*FOG_MAP_SIZE+
565  if (the_map.cells == NULL) {
566  LOG(LOG_ERROR, "mapdata_init", "%s\n", "out of memory");
567  exit(1);
568  }
569 
570  /* Skip past the first row of pointers to rows and assign the
571  * start of the actual map data
572  */
573  the_map.cells[0] = (struct MapCell *)((char *)the_map.cells+(sizeof(struct MapCell *)*FOG_MAP_SIZE));
574 
575  /* Finish assigning the beginning of each row relative to the
576  * first row assigned above
577  */
578  for (i = 0; i < FOG_MAP_SIZE; i++) {
580  }
583  }
584 
585  width = 0;
586  height = 0;
587  pl_pos.x = FOG_MAP_SIZE/2-width/2;
588  pl_pos.y = FOG_MAP_SIZE/2-height/2;
589 
590  for (x = 0; x < FOG_MAP_SIZE; x++) {
591  clear_cells(x, 0, FOG_MAP_SIZE);
592  }
593 
594  for (y = 0; y < MAX_VIEW; y++) {
595  for (x = 0; x < MAX_VIEW; x++) {
596  for (i = 0; i < MAXLAYERS; i++) {
597  bigfaces[x][y][i].next = NULL;
598  bigfaces[x][y][i].prev = NULL;
599  bigfaces[x][y][i].head.face = 0;
600  bigfaces[x][y][i].head.size_x = 1;
601  bigfaces[x][y][i].head.size_y = 1;
602  bigfaces[x][y][i].tail.face = 0;
603  bigfaces[x][y][i].tail.size_x = 0;
604  bigfaces[x][y][i].tail.size_y = 0;
605  bigfaces[x][y][i].x = x;
606  bigfaces[x][y][i].y = y;
607  bigfaces[x][y][i].layer = i;
608  }
609  }
610  }
611  bigfaces_head = NULL;
612 }
613 
614 void mapdata_set_size(int viewx, int viewy)
615 {
616  mapdata_init();
617 
618  width = viewx;
619  height = viewy;
620  pl_pos.x = FOG_MAP_SIZE/2-width/2;
621  pl_pos.y = FOG_MAP_SIZE/2-height/2;
622 }
623 
624 int mapdata_is_inside(int x, int y)
625 {
626  return(x >= 0 && x < width && y >= 0 && y < height);
627 }
628 
629 /* mapdate_clear_space() is used by Map2Cmd()
630  * Basically, server has told us there is nothing on
631  * this space. So clear it.
632  */
633 void mapdata_clear_space(int x, int y)
634 {
635  int px, py;
636  int i;
637 
638  assert(0 <= x && x < MAX_VIEW);
639  assert(0 <= y && y < MAX_VIEW);
640 
641  px = pl_pos.x+x;
642  py = pl_pos.y+y;
643  assert(0 <= px && px < FOG_MAP_SIZE);
644  assert(0 <= py && py < FOG_MAP_SIZE);
645 
646  if (x < width && y < height) {
647  /* tile is visible */
648 
649  /* visible tile is now blank ==> do not clear but mark as cleared */
650  if (!mapdata_cell(px, py)->cleared) {
651  mapdata_cell(px, py)->cleared = 1;
652  mapdata_cell(px, py)->need_update = 1;
653 
654  for (i=0; i < MAXLAYERS; i++)
655  if (mapdata_cell(px, py)->heads[i].face) {
657  }
658  }
659  } else {
660  /* tile is invisible (outside view area, i.e. big face update) */
661 
662  for (i = 0; i < MAXLAYERS; i++) {
663  expand_set_bigface(x, y, i, 0, TRUE);
664  }
665  }
666 }
667 
668 
669 /* With map2, we basically process a piece of data at a time. Thus,
670  * for each piece, we don't know what the final state of the space
671  * will be. So once Map2Cmd() has processed all the information for
672  * a space, it calls mapdata_set_check_space() which can see if
673  * the space is cleared or other inconsistencies.
674  */
676 {
677  int px, py;
678  int is_blank;
679  int i;
680  struct MapCell *cell;
681 
682  assert(0 <= x && x < MAX_VIEW);
683  assert(0 <= y && y < MAX_VIEW);
684 
685  px = pl_pos.x+x;
686  py = pl_pos.y+y;
687 
688  assert(0 <= px && px < FOG_MAP_SIZE);
689  assert(0 <= py && py < FOG_MAP_SIZE);
690 
691 
692  is_blank=1;
693  cell = mapdata_cell(px, py);
694  for (i=0; i < MAXLAYERS; i++) {
695  if (cell->heads[i].face>0 || cell->tails[i].face>0) {
696  is_blank=0;
697  break;
698  }
699  }
700 
701  if (cell->have_darkness) {
702  is_blank=0;
703  }
704 
705  /* We only care if this space needs to be blanked out */
706  if (!is_blank) {
707  return;
708  }
709 
710  if (x < width && y < height) {
711  /* tile is visible */
712 
713  /* visible tile is now blank ==> do not clear but mark as cleared */
714  if (!mapdata_cell(px, py)->cleared) {
715  mapdata_cell(px, py)->cleared = 1;
716  mapdata_cell(px, py)->need_update = 1;
717 
718  for (i=0; i < MAXLAYERS; i++) {
720  }
721  }
722  }
723 }
724 
725 
726 
727 /* This just sets the darkness for a space.
728  * Used by Map2Cmd()
729  */
730 void mapdata_set_darkness(int x, int y, int darkness)
731 {
732  int px, py;
733 
734  assert(0 <= x && x < MAX_VIEW);
735  assert(0 <= y && y < MAX_VIEW);
736 
737  px = pl_pos.x+x;
738  py = pl_pos.y+y;
739  assert(0 <= px && px < FOG_MAP_SIZE);
740  assert(0 <= py && py < FOG_MAP_SIZE);
741 
742  /* Ignore darkness information for tile outside the viewable area: if
743  * such a tile becomes visible again, it is either "fog of war" (and
744  * darkness information is ignored) or it will be updated (including
745  * the darkness information).
746  */
747  if (darkness != -1 && x < width && y < height) {
748  set_darkness(px, py, 255-darkness);
749  }
750 }
751 
752 /* Sets smooth information for layer */
753 void mapdata_set_smooth(int x, int y, int smooth, int layer)
754 {
755  static int dx[8]= {0,1,1,1,0,-1,-1,-1};
756  static int dy[8]= {-1,-1,0,1,1,1,0,-1};
757  int rx, ry, px, py, i;
758 
759  assert(0 <= x && x < MAX_VIEW);
760  assert(0 <= y && y < MAX_VIEW);
761 
762  px = pl_pos.x+x;
763  py = pl_pos.y+y;
764  assert(0 <= px && px < FOG_MAP_SIZE);
765  assert(0 <= py && py < FOG_MAP_SIZE);
766 
767  if (mapdata_cell(px, py)->smooth[layer] != smooth) {
768  for (i=0; i<8; i++) {
769  rx=px+dx[i];
770  ry=py+dy[i];
771  if ( (rx<0) || (ry<0) || (the_map.x<=rx) || (the_map.y<=ry)) {
772  continue;
773  }
774  the_map.cells[rx][ry].need_resmooth=1;
775  }
776  mapdata_cell(px, py)->need_resmooth=1;
777  mapdata_cell(px, py)->smooth[layer] = smooth;
778  }
779 }
780 
781 /* If old cell data is set and is to be cleared, clear it.
782  * This used to be in mapdata_set_face_layer(), however it needs to be
783  * called here, earlier in the Map2Cmd() because otherwise darkness
784  * doesn't work went sent before the layer data when that square was
785  * going to be cleared. This is used by the Map2Cmd()
786  */
787 void mapdata_clear_old(int x, int y)
788 {
789  int px, py;
790  int i;
791 
792  assert(0 <= x && x < MAX_VIEW);
793  assert(0 <= y && y < MAX_VIEW);
794 
795  px = pl_pos.x+x;
796  py = pl_pos.y+y;
797  assert(0 <= px && px < FOG_MAP_SIZE);
798  assert(0 <= py && py < FOG_MAP_SIZE);
799 
800  if (x < width && y < height)
801  if (mapdata_cell(px, py)->cleared) {
802  for (i=0; i < MAXLAYERS; i++) {
803  expand_clear_face_from_layer(px, py, i);
804  }
805 
806  mapdata_cell(px, py)->darkness = 0;
807  mapdata_cell(px, py)->have_darkness = 0;
808  }
809 }
810 
811 /* This is vaguely related to the mapdata_set_face() above, but rather
812  * than take all the faces, takes 1 face and the layer this face is
813  * on. This is used by the Map2Cmd()
814  */
815 void mapdata_set_face_layer(int x, int y, gint16 face, int layer)
816 {
817  int px, py;
818 
819  assert(0 <= x && x < MAX_VIEW);
820  assert(0 <= y && y < MAX_VIEW);
821 
822  px = pl_pos.x+x;
823  py = pl_pos.y+y;
824  assert(0 <= px && px < FOG_MAP_SIZE);
825  assert(0 <= py && py < FOG_MAP_SIZE);
826 
827  if (x < width && y < height) {
828  mapdata_cell(px, py)->need_update = 1;
829  if (face >0) {
830  expand_set_face(px, py, layer, face, TRUE);
831  } else {
832  expand_clear_face_from_layer(px, py, layer);
833  }
834 
835  mapdata_cell(px, py)->cleared = 0;
836  } else {
837  expand_set_bigface(x, y, layer, face, TRUE);
838  }
839 }
840 
841 
842 /* This is vaguely related to the mapdata_set_face() above, but rather
843  * than take all the faces, takes 1 face and the layer this face is
844  * on. This is used by the Map2Cmd()
845  */
846 void mapdata_set_anim_layer(int x, int y, guint16 anim, guint8 anim_speed, int layer)
847 {
848  int px, py;
849  int i, face, animation, phase, speed_left;
850 
851  assert(0 <= x && x < MAX_VIEW);
852  assert(0 <= y && y < MAX_VIEW);
853 
854  px = pl_pos.x+x;
855  py = pl_pos.y+y;
856  assert(0 <= px && px < FOG_MAP_SIZE);
857  assert(0 <= py && py < FOG_MAP_SIZE);
858 
859  animation = anim & ANIM_MASK;
860  face = 0;
861 
862  /* Random animation is pretty easy */
863  if ((anim & ANIM_FLAGS_MASK) == ANIM_RANDOM) {
864  phase = g_random_int() % animations[animation].num_animations;
865  face = animations[animation].faces[phase];
866  speed_left = anim_speed % g_random_int();
867  } else if ((anim & ANIM_FLAGS_MASK) == ANIM_SYNC) {
868  animations[animation].speed = anim_speed;
869  phase = animations[animation].phase;
870  speed_left = animations[animation].speed_left;
871  face = animations[animation].faces[phase];
872  }
873 
874  if (x < width && y < height) {
875  mapdata_cell(px, py)->need_update = 1;
876  if (mapdata_cell(px, py)->cleared) {
877  for (i=0; i < MAXLAYERS; i++) {
878  expand_clear_face_from_layer(px, py, i);
879  }
880 
881  mapdata_cell(px, py)->darkness = 0;
882  mapdata_cell(px, py)->have_darkness = 0;
883  }
884  if (face >0) {
885  expand_set_face(px, py, layer, face, TRUE);
886  mapdata_cell(px, py)->heads[layer].animation = animation;
887  mapdata_cell(px, py)->heads[layer].animation_phase = phase;
888  mapdata_cell(px, py)->heads[layer].animation_speed = anim_speed;
889  mapdata_cell(px, py)->heads[layer].animation_left = speed_left;
890  } else {
891  expand_clear_face_from_layer(px, py, layer);
892  }
893 
894  mapdata_cell(px, py)->cleared = 0;
895 
896  } else {
897  expand_set_bigface(x, y, layer, face, TRUE);
898  }
899 }
900 
901 
902 void mapdata_scroll(int dx, int dy)
903 {
904  int x, y;
905 
907 
909  struct BigCell *cell;
910 
911  /* Mark all tiles as "need_update" that are overlapped by a big face
912  * from outside the view area.
913  */
914  for (cell = bigfaces_head; cell != NULL; cell = cell->next) {
915  for (x = 0; x < cell->head.size_x; x++) {
916  for (y = !x; y < cell->head.size_y; y++) {
917  if (0 <= cell->x-x && cell->x-x < width
918  && 0 <= cell->y-y && cell->y-y < height) {
919  the_map.cells[pl_pos.x+cell->x-x][pl_pos.y+cell->y-y].need_update = 1;
920  }
921  }
922  }
923  }
924  } else {
925  /* Emulate map scrolling by redrawing all tiles. */
926  for (x = 0; x < width; x++) {
927  for (y = 0; y < height; y++) {
929  }
930  }
931  }
932 
933  pl_pos.x += dx;
934  pl_pos.y += dy;
935 
936  /* clear all newly visible tiles */
937  if (dx > 0) {
938  for (y = 0; y < height; y++) {
939  for (x = width-dx; x < width; x++) {
942  }
943  }
944  } else {
945  for (y = 0; y < height; y++) {
946  for (x = 0; x < -dx; x++) {
949  }
950  }
951  }
952 
953  if (dy > 0) {
954  for (x = 0; x < width; x++) {
955  for (y = height-dy; y < height; y++) {
958  }
959  }
960  } else {
961  for (x = 0; x < width; x++) {
962  for (y = 0; y < -dy; y++) {
965  }
966  }
967  }
968 
969  /* Remove all big faces outside the view area. */
970  while (bigfaces_head != NULL) {
971  expand_clear_bigface_from_layer(bigfaces_head->x, bigfaces_head->y, bigfaces_head->layer, 0);
972  }
973 }
974 
975 void mapdata_newmap(void)
976 {
977  int x, y;
978 
979  /* Clear the_map.cells[]. */
980  for (x = 0; x < FOG_MAP_SIZE; x++) {
981  clear_cells(x, 0, FOG_MAP_SIZE);
982  for (y = 0; y < FOG_MAP_SIZE; y++) {
983  mapdata_cell(x, y)->need_update = 1;
984  }
985  }
986 
987  /* Clear bigfaces[]. */
988  while (bigfaces_head != NULL) {
989  expand_clear_bigface_from_layer(bigfaces_head->x, bigfaces_head->y, bigfaces_head->layer, 0);
990  }
991 }
992 
996 static bool mapdata_has_tile(int x, int y, int layer) {
997  if (0 <= x && x < width && 0 <= y && y < height) {
998  if (0 <= layer && layer < MAXLAYERS) {
999  return true;
1000  }
1001  }
1002 
1003  return false;
1004 }
1005 
1013 gint16 mapdata_face(int x, int y, int layer) {
1014  if (!mapdata_has_tile(x, y, layer)) {
1015  return 0;
1016  }
1017 
1018  return the_map.cells[pl_pos.x+x][pl_pos.y+y].heads[layer].face;
1019 }
1020 
1021 gint16 mapdata_face_info(int mx, int my, int layer, int *dx, int *dy) {
1022  struct MapCellLayer *head = &the_map.cells[mx][my].heads[layer];
1023  struct MapCellLayer *tail = &the_map.cells[mx][my].tails[layer];
1024  if (head->face != 0) {
1025  const int width = head->size_x, height = head->size_y;
1026  *dx = 1 - width, *dy = 1 - height;
1027  return head->face;
1028  } else if (tail->face != 0) {
1029  struct MapCellLayer *head_ptr = &the_map.cells[mx + tail->size_x][my + tail->size_y].heads[layer];
1030  const int width = head_ptr->size_x, height = head_ptr->size_y;
1031  *dx = tail->size_x - width + 1, *dy = tail->size_y - height + 1;
1032  return tail->face;
1033  } else {
1034  return 0;
1035  }
1036 }
1037 
1047 gint16 mapdata_bigface(int x, int y, int layer, int *ww, int *hh) {
1048  gint16 result;
1049 
1050  if (!mapdata_has_tile(x, y, layer)) {
1051  return 0;
1052  }
1053 
1054  result = the_map.cells[pl_pos.x+x][pl_pos.y+y].tails[layer].face;
1055  if (result != 0) {
1056  int clear_bigface;
1057  int dx = the_map.cells[pl_pos.x+x][pl_pos.y+y].tails[layer].size_x;
1058  int dy = the_map.cells[pl_pos.x+x][pl_pos.y+y].tails[layer].size_y;
1059  int w = the_map.cells[pl_pos.x+x+dx][pl_pos.y+y+dy].heads[layer].size_x;
1060  int h = the_map.cells[pl_pos.x+x+dx][pl_pos.y+y+dy].heads[layer].size_y;
1061  assert(1 <= w && w <= MAX_FACE_SIZE);
1062  assert(1 <= h && h <= MAX_FACE_SIZE);
1063  assert(0 <= dx && dx < w);
1064  assert(0 <= dy && dy < h);
1065 
1066  /* Now check if we are about to display an obsolete big face: such a
1067  * face has a cleared ("fog of war") head but the current tile is not
1068  * fog of war. Since the server would have sent an appropriate head
1069  * tile if it was already valid, just clear the big face and do not
1070  * return it.
1071  */
1072  if (the_map.cells[pl_pos.x+x][pl_pos.y+y].cleared) {
1073  /* Current face is a "fog of war" tile ==> do not clear
1074  * old information.
1075  */
1076  clear_bigface = 0;
1077  } else {
1078  if (x+dx < width && y+dy < height) {
1079  /* Clear face if current tile is valid but the
1080  * head is marked as cleared.
1081  */
1082  clear_bigface = the_map.cells[pl_pos.x+x+dx][pl_pos.y+y+dy].cleared;
1083  } else {
1084  /* Clear face if current tile is valid but the
1085  * head is not set.
1086  */
1087  clear_bigface = bigfaces[x+dx][y+dy][layer].head.face == 0;
1088  }
1089  }
1090 
1091  if (!clear_bigface) {
1092  *ww = w-1-dx;
1093  *hh = h-1-dy;
1094  return(result);
1095  }
1096 
1097  assert(the_map.cells[pl_pos.x+x][pl_pos.y+y].tails[layer].face == result);
1098  expand_clear_face_from_layer(pl_pos.x+x+dx, pl_pos.y+y+dy, layer);
1099  assert(the_map.cells[pl_pos.x+x][pl_pos.y+y].tails[layer].face == 0);
1100  }
1101 
1102  result = bigfaces[x][y][layer].tail.face;
1103  if (result != 0) {
1104  int dx = bigfaces[x][y][layer].tail.size_x;
1105  int dy = bigfaces[x][y][layer].tail.size_y;
1106  int w = bigfaces[x+dx][y+dy][layer].head.size_x;
1107  int h = bigfaces[x+dx][y+dy][layer].head.size_y;
1108  assert(0 <= dx && dx < w);
1109  assert(0 <= dy && dy < h);
1110  *ww = w-1-dx;
1111  *hh = h-1-dy;
1112  return(result);
1113  }
1114 
1115  *ww = 1;
1116  *hh = 1;
1117  return(0);
1118 }
1119 
1120 /* This is used by the opengl logic.
1121  * Basically the opengl code draws the the entire image,
1122  * and doesn't care if if portions are off the edge
1123  * (opengl takes care of that). So basically, this
1124  * function returns only if the head for a space is set,
1125  * otherwise, returns 0 - we don't care about the tails
1126  * or other details really.
1127  */
1128 gint16 mapdata_bigface_head(int x, int y, int layer, int *ww, int *hh) {
1129  gint16 result;
1130 
1131  if (!mapdata_has_tile(x, y, layer)) {
1132  return 0;
1133  }
1134 
1135  result = bigfaces[x][y][layer].head.face;
1136  if (result != 0) {
1137  int w = bigfaces[x][y][layer].head.size_x;
1138  int h = bigfaces[x][y][layer].head.size_y;
1139  *ww = w;
1140  *hh = h;
1141  return(result);
1142  }
1143 
1144  *ww = 1;
1145  *hh = 1;
1146  return(0);
1147 }
1148 
1157 static void recenter_virtual_map_view(int diff_x, int diff_y)
1158 {
1159  int new_x, new_y;
1160  int shift_x, shift_y;
1161  int src_x, src_y;
1162  int dst_x, dst_y;
1163  int len_x, len_y;
1164  int sx;
1165  int dx;
1166  int i;
1167 
1168  /* shift player position in virtual map */
1169  new_x = pl_pos.x+diff_x;
1170  new_y = pl_pos.y+diff_y;
1171 
1172  /* determine neccessary amount to shift */
1173 
1174  /* if(new_x < 1) is not possible: a big face may reach up to
1175  * (MAX_FACE_SIZE-1) tiles to the left of pl_pos. Therefore maintain a
1176  * border of at least MAX_FACE_SIZE to the left of the virtual map
1177  * edge.
1178  */
1179  if (new_x < MAX_FACE_SIZE) {
1180  shift_x = FOG_BORDER_MIN+MAX_FACE_SIZE-new_x;
1181  /* This yields: new_x+shift_x == FOG_BORDER_MIN+MAX_FACE_SIZE,
1182  * i.e. left border is FOG_BORDER_MIN+MAX_FACE_SIZE after
1183  * shifting.
1184  */
1185  } else if (new_x+MAX_VIEW > FOG_MAP_SIZE) {
1186  shift_x = FOG_MAP_SIZE-FOG_BORDER_MIN-MAX_VIEW-new_x;
1187  /* This yields: new_x+shift_x ==
1188  * FOG_MAP_SIZE-FOG_BODER_MIN-MAX_VIEW, i.e. right border is
1189  * FOGBORDER_MIN after shifting.
1190  */
1191  } else {
1192  shift_x = 0;
1193  }
1194 
1195  /* Same as above but for y. */
1196  if (new_y < MAX_FACE_SIZE) {
1197  shift_y = FOG_BORDER_MIN+MAX_FACE_SIZE-new_y;
1198  } else if (new_y+MAX_VIEW > FOG_MAP_SIZE) {
1199  shift_y = FOG_MAP_SIZE-FOG_BORDER_MIN-MAX_VIEW-new_y;
1200  } else {
1201  shift_y = 0;
1202  }
1203 
1204  /* No shift neccessary? ==> nothing to do. */
1205  if (shift_x == 0 && shift_y == 0) {
1206  return;
1207  }
1208 
1209  /* If shifting at all: maintain a border size of FOG_BORDER_MIN to all
1210  * directions. For example: if pl_pos=30/MAX_FACE_SIZE, and map_scroll is
1211  * 0/-1: shift pl_pos to FOG_BORDER_MIN+1/FOG_BORDER_MIN+1, not to
1212  * 30/FOG_BORDER_MIN+1.
1213  */
1214  if (shift_x == 0) {
1215  if (new_x < FOG_BORDER_MIN+MAX_FACE_SIZE) {
1216  shift_x = FOG_BORDER_MIN+MAX_FACE_SIZE-new_x;
1217  } else if (new_x+MAX_VIEW+FOG_BORDER_MIN > FOG_MAP_SIZE) {
1218  shift_x = FOG_MAP_SIZE-FOG_BORDER_MIN-MAX_VIEW-new_x;
1219  }
1220  }
1221  if (shift_y == 0) {
1222  if (new_y < FOG_BORDER_MIN+MAX_FACE_SIZE) {
1223  shift_y = FOG_BORDER_MIN+MAX_FACE_SIZE-new_y;
1224  } else if (new_y+MAX_VIEW+FOG_BORDER_MIN > FOG_MAP_SIZE) {
1225  shift_y = FOG_MAP_SIZE-FOG_BORDER_MIN-MAX_VIEW-new_y;
1226  }
1227  }
1228 
1229  /* Shift for more than virtual map size? ==> clear whole virtual map
1230  * and recenter.
1231  */
1232  if (shift_x <= -FOG_MAP_SIZE || shift_x >= FOG_MAP_SIZE
1233  || shift_y <= -FOG_MAP_SIZE || shift_y >= FOG_MAP_SIZE) {
1234  for (dx = 0; dx < FOG_MAP_SIZE; dx++) {
1235  clear_cells(dx, 0, FOG_MAP_SIZE);
1236  }
1237 
1238  pl_pos.x = FOG_MAP_SIZE/2-width/2;
1239  pl_pos.y = FOG_MAP_SIZE/2-height/2;
1240  return;
1241  }
1242 
1243  /* Move player position. */
1244  pl_pos.x += shift_x;
1245  pl_pos.y += shift_y;
1246 
1247  /* Actually shift the virtual map by shift_x/shift_y */
1248  if (shift_x < 0) {
1249  src_x = -shift_x;
1250  dst_x = 0;
1251  len_x = FOG_MAP_SIZE+shift_x;
1252  } else {
1253  src_x = 0;
1254  dst_x = shift_x;
1255  len_x = FOG_MAP_SIZE-shift_x;
1256  }
1257 
1258  if (shift_y < 0) {
1259  src_y = -shift_y;
1260  dst_y = 0;
1261  len_y = FOG_MAP_SIZE+shift_y;
1262  } else {
1263  src_y = 0;
1264  dst_y = shift_y;
1265  len_y = FOG_MAP_SIZE-shift_y;
1266  }
1267 
1268  if (shift_x < 0) {
1269  for (sx = src_x, dx = dst_x, i = 0; i < len_x; sx++, dx++, i++) {
1270  /* srcx!=dstx ==> can use memcpy since source and
1271  * destination to not overlap.
1272  */
1273  memcpy(&the_map.cells[dx][dst_y], &the_map.cells[sx][src_y], len_y*sizeof(the_map.cells[dx][dst_y]));
1274  }
1275  } else if (shift_x > 0) {
1276  for (sx = src_x+len_x-1, dx = dst_x+len_x-1, i = 0; i < len_x; sx--, dx--, i++) {
1277  /* srcx!=dstx ==> can use memcpy since source and
1278  * destination to not overlap.
1279  */
1280  memcpy(&the_map.cells[dx][dst_y], &the_map.cells[sx][src_y], len_y*sizeof(the_map.cells[dx][dst_y]));
1281  }
1282  } else {
1283  assert(src_x == dst_x);
1284  for (dx = src_x, i = 0; i < len_x; dx++, i++) {
1285  /* srcx==dstx ==> use memmove since source and
1286  * destination probably do overlap.
1287  */
1288  memmove(&the_map.cells[dx][dst_y], &the_map.cells[dx][src_y], len_y*sizeof(the_map.cells[dx][dst_y]));
1289  }
1290  }
1291 
1292  /* Clear newly opened area */
1293  for (dx = 0; dx < dst_x; dx++) {
1294  clear_cells(dx, 0, FOG_MAP_SIZE);
1295  }
1296  for (dx = dst_x+len_x; dx < FOG_MAP_SIZE; dx++) {
1297  clear_cells(dx, 0, FOG_MAP_SIZE);
1298  }
1299  if (shift_y > 0) {
1300  for (dx = 0; dx < len_x; dx++) {
1301  clear_cells(dx+dst_x, 0, shift_y);
1302  }
1303  } else if (shift_y < 0) {
1304  for (dx = 0; dx < len_x; dx++) {
1305  clear_cells(dx+dst_x, FOG_MAP_SIZE+shift_y, -shift_y);
1306  }
1307  }
1308 }
1309 
1314 static void mapdata_get_image_size(int face, guint8 *w, guint8 *h)
1315 {
1316  get_map_image_size(face, w, h);
1317  if (*w < 1) {
1318  *w = 1;
1319  }
1320  if (*h < 1) {
1321  *h = 1;
1322  }
1323  if (*w > MAX_FACE_SIZE) {
1324  *w = MAX_FACE_SIZE;
1325  }
1326  if (*h > MAX_FACE_SIZE) {
1327  *h = MAX_FACE_SIZE;
1328  }
1329 }
1330 
1331 /* This basically goes through all the map spaces and does the necessary
1332  * animation.
1333  */
1335 {
1336  int x, y, layer, face;
1337  struct MapCellLayer *cell;
1338 
1339 
1340  /* For synchronized animations, what we do is set the initial values
1341  * in the mapdata to the fields in the animations[] array. In this way,
1342  * the code below the iterates the spaces doesn't need to do anything
1343  * special. But we have to update the animations[] array here to
1344  * keep in sync.
1345  */
1346  for (x=0; x < MAXANIM; x++) {
1347  if (animations[x].speed) {
1348  animations[x].speed_left++;
1349  if (animations[x].speed_left >= animations[x].speed) {
1350  animations[x].speed_left=0;
1351  animations[x].phase++;
1352  if (animations[x].phase >= animations[x].num_animations) {
1353  animations[x].phase=0;
1354  }
1355  }
1356  }
1357  }
1358 
1359  for (x=0; x < CURRENT_MAX_VIEW; x++) {
1360  for (y=0; y < CURRENT_MAX_VIEW; y++) {
1361 
1362  /* Short cut some processing here. It makes sense to me
1363  * not to animate stuff out of view
1364  */
1365  if (the_map.cells[pl_pos.x + x][pl_pos.y + y].cleared) {
1366  continue;
1367  }
1368 
1369  for (layer=0; layer<MAXLAYERS; layer++) {
1370  /* Using the cell structure just makes life easier here */
1371  cell = &the_map.cells[pl_pos.x+x][pl_pos.y+y].heads[layer];
1372 
1373  if (cell->animation) {
1374  cell->animation_left++;
1375  if (cell->animation_left >= cell->animation_speed) {
1376  cell->animation_left=0;
1377  cell->animation_phase++;
1378  if (cell->animation_phase >= animations[cell->animation].num_animations) {
1379  cell->animation_phase=0;
1380  }
1381  face = animations[cell->animation].faces[cell->animation_phase];
1382 
1383  /* I don't think we send any to the client, but it is possible
1384  * for animations to have blank faces.
1385  */
1386  if (face >0) {
1387  expand_set_face(pl_pos.x + x, pl_pos.y + y, layer, face, FALSE);
1388  } else {
1389  expand_clear_face_from_layer(pl_pos.x + x, pl_pos.y + y , layer);
1390  }
1391  }
1392  }
1393  cell = &bigfaces[x][y][layer].head;
1394  if (cell->animation) {
1395  cell->animation_left++;
1396  if (cell->animation_left >= cell->animation_speed) {
1397  cell->animation_left=0;
1398  cell->animation_phase++;
1399  if (cell->animation_phase >= animations[cell->animation].num_animations) {
1400  cell->animation_phase=0;
1401  }
1402  face = animations[cell->animation].faces[cell->animation_phase];
1403 
1404  /* I don't think we send any to the client, but it is possible
1405  * for animations to have blank faces.
1406  */
1407  expand_set_bigface(x, y, layer, face, FALSE);
1408  }
1409  }
1410  }
1411  }
1412  }
1413 }
Animations animations[MAXANIM]
Definition: commands.c:1127
static int height
Definition: mapdata.c:82
The heads[] in the mapcell is used for single part objects or the head piece for multipart.
Definition: mapdata.h:49
int y
Definition: mapdata.h:67
gint16 mapdata_bigface(int x, int y, int layer, int *ww, int *hh)
Return the face number of a multi-square pixmap at the given map tile.
Definition: mapdata.c:1047
guint8 have_darkness
Definition: mapdata.h:56
void get_map_image_size(int face, guint8 *w, guint8 *h)
Definition: image.c:493
#define ANIM_RANDOM
Definition: newclient.h:322
gint16 use_config[CONFIG_NUMS]
Definition: init.c:40
void mapdata_animation(void)
Definition: mapdata.c:1334
void mapdata_set_check_space(int x, int y)
Definition: mapdata.c:675
void mapdata_clear_space(int x, int y)
Definition: mapdata.c:633
guint8 num_animations
Number of animations.
Definition: client.h:100
#define CONFIG_LIGHTING
Definition: client.h:201
#define CONFIG_DISPLAYMODE
Definition: client.h:194
struct MapCell * mapdata_cell(int x, int y)
Get the stored map cell at the given map coordinate.
Definition: mapdata.c:119
void mapdata_set_face_layer(int x, int y, gint16 face, int layer)
Definition: mapdata.c:815
guint16 smooth[MAXLAYERS]
Definition: mapdata.h:53
static void expand_clear_face(int x, int y, int w, int h, int layer)
Clear a face from the_map.cells[].
Definition: mapdata.c:213
struct MapCellLayer tails[MAXLAYERS]
Definition: mapdata.h:52
static void expand_need_update(int x, int y, int w, int h)
Mark a face as "need_update".
Definition: mapdata.c:511
Contains external calls that the common area makes callbacks to.
#define CFG_LT_PIXEL_BEST
Definition: client.h:231
#define ANIM_MASK
AND&#39;ing this with data from server gets us just the animation id.
Definition: newclient.h:331
#define ANIM_FLAGS_MASK
Used only by the client.
Definition: newclient.h:325
static void mapdata_get_image_size(int face, guint8 *w, guint8 *h)
Return the size of a face in tiles.
Definition: mapdata.c:1314
void mapdata_newmap(void)
Clears the map view.
Definition: mapdata.c:975
gint16 animation
Definition: mapdata.h:30
gint8 size_x
Definition: mapdata.h:20
#define CONFIG_MAPSCROLL
Use bitmap operations for map scrolling.
Definition: client.h:213
static void expand_need_update_from_layer(int x, int y, int layer)
Mark a face as "need_update".
Definition: mapdata.c:539
void mapdata_set_anim_layer(int x, int y, guint16 anim, guint8 anim_speed, int layer)
Definition: mapdata.c:846
gint16 mapdata_face(int x, int y, int layer)
Return the face number of a single-square pixmap at the given map tile.
Definition: mapdata.c:1013
gint16 mapdata_bigface_head(int x, int y, int layer, int *ww, int *hh)
Definition: mapdata.c:1128
static void recenter_virtual_map_view(int diff_x, int diff_y)
Check if current map position is out of bounds if shifted by (dx, dy).
Definition: mapdata.c:1157
static int width
Viewable map size, in number of tiles.
Definition: mapdata.c:82
void LOG(LogLevel level, const char *origin, const char *format,...)
Log messages of a certain importance to stderr.
Definition: misc.c:109
guint16 x
Definition: mapdata.c:70
#define FOG_BORDER_MIN
After shifting the virtual map: new minimum distance of the view area to the new virtual map border...
Definition: mapdata.c:36
guint8 cleared
Definition: mapdata.h:58
static struct BigCell * bigfaces_head
Contains the head of a list of all currently active big faces outside the view area.
Definition: mapdata.c:89
static void expand_set_bigface(int x, int y, int layer, gint16 face, int clear)
Update a face into bigfaces[].
Definition: mapdata.c:446
guint8 speed
Definition: client.h:104
bool mapdata_can_smooth(int x, int y, int layer)
Definition: mapdata.c:134
static void mark_resmooth(int x, int y, int layer)
Definition: mapdata.c:192
Definition: mapdata.h:61
gint8 size_y
Definition: mapdata.h:21
#define FOG_MAP_SIZE
Size of virtual map.
Definition: mapdata.c:30
void mapdata_size(int *x, int *y)
Determine the size of the internal fog-of-war map.
Definition: mapdata.c:142
struct MapCellLayer head
Definition: mapdata.c:67
void mapdata_clear_old(int x, int y)
Definition: mapdata.c:787
int display_mapscroll(int dx, int dy)
Definition: map.c:122
struct Map the_map
Definition: mapdata.c:99
static void expand_clear_bigface_from_layer(int x, int y, int layer, int set_need_update)
Clear a face from bigfaces[].
Definition: mapdata.c:400
void mapdata_init(void)
Initializes the module.
Definition: mapdata.c:556
struct MapCell ** cells
Definition: mapdata.h:69
guint8 need_resmooth
Definition: mapdata.h:57
gint16 mapdata_face_info(int mx, int my, int layer, int *dx, int *dy)
Return the face number of the pixmap in the given map cell and set the offset pointers to indicate wh...
Definition: mapdata.c:1021
int x
Definition: mapdata.h:66
static void set_darkness(int x, int y, int darkness)
Update darkness information.
Definition: mapdata.c:160
gint16 want_config[CONFIG_NUMS]
Definition: init.c:40
static void expand_clear_face_from_layer(int x, int y, int layer)
Clear a face from the_map.cells[].
Definition: mapdata.c:268
bool mapdata_contains(int x, int y)
Determine whether the map data contains the given cell.
Definition: mapdata.c:126
static void expand_clear_bigface(int x, int y, int w, int h, int layer, int set_need_update)
Clear a face from bigfaces[].
Definition: mapdata.c:346
#define ANIM_SYNC
Definition: newclient.h:323
Warning that something definitely didn&#39;t work.
Definition: client.h:444
static bool mapdata_has_tile(int x, int y, int layer)
Check if the given map tile is a valid slot in the map array.
Definition: mapdata.c:996
guint8 animation_speed
Definition: mapdata.h:31
#define MAXLAYERS
The protocol supports 10 layers, so set MAXLAYERS accordingly.
Definition: mapdata.h:6
guint8 need_update
Definition: mapdata.h:55
void mapdata_scroll(int dx, int dy)
Scrolls the map view.
Definition: mapdata.c:902
static void clear_cells(int x, int y, int len_y)
Clear cells the_map.cells[x][y..y+len_y-1].
Definition: mapdata.c:104
static void expand_set_face(int x, int y, int layer, gint16 face, int clear)
Update a face into the_map.cells[].
Definition: mapdata.c:295
guint16 y
Definition: mapdata.c:70
#define CURRENT_MAX_VIEW
Definition: mapdata.c:48
#define CFG_DM_SDL
Definition: client.h:240
guint16 * faces
Definition: client.h:107
guint8 speed_left
Definition: client.h:105
int mapdata_is_inside(int x, int y)
Checks whether the given coordinates are within the current display size (as set by mapdata_set_size)...
Definition: mapdata.c:624
struct MapCellLayer tail
Definition: mapdata.c:68
#define CFG_LT_PIXEL
Definition: client.h:230
struct BigCell * next
Definition: mapdata.c:64
guint8 animation_phase
Definition: mapdata.h:33
Includes various dependencies header files needed by most everything.
#define MAX_VIEW
Maximum size of view area a server could support.
Definition: mapdata.h:11
#define MAX_FACE_SIZE
Maximum size of a big face image in tiles.
Definition: mapdata.c:41
gint16 face
Definition: mapdata.h:19
struct MapCellLayer heads[MAXLAYERS]
Definition: mapdata.h:51
#define MAXANIM
Definition: client.h:86
guint8 layer
Definition: mapdata.c:71
static struct BigCell bigfaces[MAX_VIEW][MAX_VIEW][MAXLAYERS]
The variable bigfaces[] contains information about big faces (faces with a width or height >1)...
Definition: mapdata.c:96
The struct BigCell describes a tile outside the view area.
Definition: mapdata.c:63
void mapdata_set_size(int viewx, int viewy)
Sets the current display size.
Definition: mapdata.c:614
guint8 animation_left
Definition: mapdata.h:32
guint8 darkness
Definition: mapdata.h:54
void mapdata_set_darkness(int x, int y, int darkness)
Definition: mapdata.c:730
PlayerPosition pl_pos
Definition: map.c:37
guint8 phase
Definition: client.h:106
struct BigCell * prev
Definition: mapdata.c:65
void mapdata_set_smooth(int x, int y, int smooth, int layer)
Definition: mapdata.c:753