Crossfire Client, Trunk  R20693
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  */
675 void mapdata_set_check_space(int x, int y)
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  const guint8 num_animations = animations[animation].num_animations;
865  if (num_animations == 0) {
866  LOG(LOG_WARNING, "mapdata_set_anim_layer",
867  "animating object with zero animations");
868  return;
869  }
870  phase = g_random_int() % num_animations;
871  face = animations[animation].faces[phase];
872  speed_left = anim_speed % g_random_int();
873  } else if ((anim & ANIM_FLAGS_MASK) == ANIM_SYNC) {
874  animations[animation].speed = anim_speed;
875  phase = animations[animation].phase;
876  speed_left = animations[animation].speed_left;
877  face = animations[animation].faces[phase];
878  }
879 
880  if (x < width && y < height) {
881  mapdata_cell(px, py)->need_update = 1;
882  if (mapdata_cell(px, py)->cleared) {
883  for (i=0; i < MAXLAYERS; i++) {
884  expand_clear_face_from_layer(px, py, i);
885  }
886 
887  mapdata_cell(px, py)->darkness = 0;
888  mapdata_cell(px, py)->have_darkness = 0;
889  }
890  if (face >0) {
891  expand_set_face(px, py, layer, face, TRUE);
892  mapdata_cell(px, py)->heads[layer].animation = animation;
893  mapdata_cell(px, py)->heads[layer].animation_phase = phase;
894  mapdata_cell(px, py)->heads[layer].animation_speed = anim_speed;
895  mapdata_cell(px, py)->heads[layer].animation_left = speed_left;
896  } else {
897  expand_clear_face_from_layer(px, py, layer);
898  }
899 
900  mapdata_cell(px, py)->cleared = 0;
901 
902  } else {
903  expand_set_bigface(x, y, layer, face, TRUE);
904  }
905 }
906 
907 
908 void mapdata_scroll(int dx, int dy)
909 {
910  int x, y;
911 
913 
915  struct BigCell *cell;
916 
917  /* Mark all tiles as "need_update" that are overlapped by a big face
918  * from outside the view area.
919  */
920  for (cell = bigfaces_head; cell != NULL; cell = cell->next) {
921  for (x = 0; x < cell->head.size_x; x++) {
922  for (y = !x; y < cell->head.size_y; y++) {
923  if (0 <= cell->x-x && cell->x-x < width
924  && 0 <= cell->y-y && cell->y-y < height) {
925  the_map.cells[pl_pos.x+cell->x-x][pl_pos.y+cell->y-y].need_update = 1;
926  }
927  }
928  }
929  }
930  } else {
931  /* Emulate map scrolling by redrawing all tiles. */
932  for (x = 0; x < width; x++) {
933  for (y = 0; y < height; y++) {
935  }
936  }
937  }
938 
939  pl_pos.x += dx;
940  pl_pos.y += dy;
941 
942  /* clear all newly visible tiles */
943  if (dx > 0) {
944  for (y = 0; y < height; y++) {
945  for (x = width-dx; x < width; x++) {
948  }
949  }
950  } else {
951  for (y = 0; y < height; y++) {
952  for (x = 0; x < -dx; x++) {
955  }
956  }
957  }
958 
959  if (dy > 0) {
960  for (x = 0; x < width; x++) {
961  for (y = height-dy; y < height; y++) {
964  }
965  }
966  } else {
967  for (x = 0; x < width; x++) {
968  for (y = 0; y < -dy; y++) {
971  }
972  }
973  }
974 
975  /* Remove all big faces outside the view area. */
976  while (bigfaces_head != NULL) {
977  expand_clear_bigface_from_layer(bigfaces_head->x, bigfaces_head->y, bigfaces_head->layer, 0);
978  }
979 }
980 
981 void mapdata_newmap(void)
982 {
983  int x, y;
984 
985  /* Clear the_map.cells[]. */
986  for (x = 0; x < FOG_MAP_SIZE; x++) {
987  clear_cells(x, 0, FOG_MAP_SIZE);
988  for (y = 0; y < FOG_MAP_SIZE; y++) {
989  mapdata_cell(x, y)->need_update = 1;
990  }
991  }
992 
993  /* Clear bigfaces[]. */
994  while (bigfaces_head != NULL) {
995  expand_clear_bigface_from_layer(bigfaces_head->x, bigfaces_head->y, bigfaces_head->layer, 0);
996  }
997 }
998 
1002 static bool mapdata_has_tile(int x, int y, int layer) {
1003  if (0 <= x && x < width && 0 <= y && y < height) {
1004  if (0 <= layer && layer < MAXLAYERS) {
1005  return true;
1006  }
1007  }
1008 
1009  return false;
1010 }
1011 
1019 gint16 mapdata_face(int x, int y, int layer) {
1020  if (!mapdata_has_tile(x, y, layer)) {
1021  return 0;
1022  }
1023 
1024  return the_map.cells[pl_pos.x+x][pl_pos.y+y].heads[layer].face;
1025 }
1026 
1027 gint16 mapdata_face_info(int mx, int my, int layer, int *dx, int *dy) {
1028  struct MapCellLayer *head = &the_map.cells[mx][my].heads[layer];
1029  struct MapCellLayer *tail = &the_map.cells[mx][my].tails[layer];
1030  if (head->face != 0) {
1031  const int width = head->size_x, height = head->size_y;
1032  *dx = 1 - width, *dy = 1 - height;
1033  return head->face;
1034  } else if (tail->face != 0) {
1035  struct MapCellLayer *head_ptr = &the_map.cells[mx + tail->size_x][my + tail->size_y].heads[layer];
1036  const int width = head_ptr->size_x, height = head_ptr->size_y;
1037  *dx = tail->size_x - width + 1, *dy = tail->size_y - height + 1;
1038  return tail->face;
1039  } else {
1040  return 0;
1041  }
1042 }
1043 
1053 gint16 mapdata_bigface(int x, int y, int layer, int *ww, int *hh) {
1054  gint16 result;
1055 
1056  if (!mapdata_has_tile(x, y, layer)) {
1057  return 0;
1058  }
1059 
1060  result = the_map.cells[pl_pos.x+x][pl_pos.y+y].tails[layer].face;
1061  if (result != 0) {
1062  int clear_bigface;
1063  int dx = the_map.cells[pl_pos.x+x][pl_pos.y+y].tails[layer].size_x;
1064  int dy = the_map.cells[pl_pos.x+x][pl_pos.y+y].tails[layer].size_y;
1065  int w = the_map.cells[pl_pos.x+x+dx][pl_pos.y+y+dy].heads[layer].size_x;
1066  int h = the_map.cells[pl_pos.x+x+dx][pl_pos.y+y+dy].heads[layer].size_y;
1067  assert(1 <= w && w <= MAX_FACE_SIZE);
1068  assert(1 <= h && h <= MAX_FACE_SIZE);
1069  assert(0 <= dx && dx < w);
1070  assert(0 <= dy && dy < h);
1071 
1072  /* Now check if we are about to display an obsolete big face: such a
1073  * face has a cleared ("fog of war") head but the current tile is not
1074  * fog of war. Since the server would have sent an appropriate head
1075  * tile if it was already valid, just clear the big face and do not
1076  * return it.
1077  */
1078  if (the_map.cells[pl_pos.x+x][pl_pos.y+y].cleared) {
1079  /* Current face is a "fog of war" tile ==> do not clear
1080  * old information.
1081  */
1082  clear_bigface = 0;
1083  } else {
1084  if (x+dx < width && y+dy < height) {
1085  /* Clear face if current tile is valid but the
1086  * head is marked as cleared.
1087  */
1088  clear_bigface = the_map.cells[pl_pos.x+x+dx][pl_pos.y+y+dy].cleared;
1089  } else {
1090  /* Clear face if current tile is valid but the
1091  * head is not set.
1092  */
1093  clear_bigface = bigfaces[x+dx][y+dy][layer].head.face == 0;
1094  }
1095  }
1096 
1097  if (!clear_bigface) {
1098  *ww = w-1-dx;
1099  *hh = h-1-dy;
1100  return(result);
1101  }
1102 
1103  assert(the_map.cells[pl_pos.x+x][pl_pos.y+y].tails[layer].face == result);
1104  expand_clear_face_from_layer(pl_pos.x+x+dx, pl_pos.y+y+dy, layer);
1105  assert(the_map.cells[pl_pos.x+x][pl_pos.y+y].tails[layer].face == 0);
1106  }
1107 
1108  result = bigfaces[x][y][layer].tail.face;
1109  if (result != 0) {
1110  int dx = bigfaces[x][y][layer].tail.size_x;
1111  int dy = bigfaces[x][y][layer].tail.size_y;
1112  int w = bigfaces[x+dx][y+dy][layer].head.size_x;
1113  int h = bigfaces[x+dx][y+dy][layer].head.size_y;
1114  assert(0 <= dx && dx < w);
1115  assert(0 <= dy && dy < h);
1116  *ww = w-1-dx;
1117  *hh = h-1-dy;
1118  return(result);
1119  }
1120 
1121  *ww = 1;
1122  *hh = 1;
1123  return(0);
1124 }
1125 
1126 /* This is used by the opengl logic.
1127  * Basically the opengl code draws the the entire image,
1128  * and doesn't care if if portions are off the edge
1129  * (opengl takes care of that). So basically, this
1130  * function returns only if the head for a space is set,
1131  * otherwise, returns 0 - we don't care about the tails
1132  * or other details really.
1133  */
1134 gint16 mapdata_bigface_head(int x, int y, int layer, int *ww, int *hh) {
1135  gint16 result;
1136 
1137  if (!mapdata_has_tile(x, y, layer)) {
1138  return 0;
1139  }
1140 
1141  result = bigfaces[x][y][layer].head.face;
1142  if (result != 0) {
1143  int w = bigfaces[x][y][layer].head.size_x;
1144  int h = bigfaces[x][y][layer].head.size_y;
1145  *ww = w;
1146  *hh = h;
1147  return(result);
1148  }
1149 
1150  *ww = 1;
1151  *hh = 1;
1152  return(0);
1153 }
1154 
1163 static void recenter_virtual_map_view(int diff_x, int diff_y)
1164 {
1165  int new_x, new_y;
1166  int shift_x, shift_y;
1167  int src_x, src_y;
1168  int dst_x, dst_y;
1169  int len_x, len_y;
1170  int sx;
1171  int dx;
1172  int i;
1173 
1174  /* shift player position in virtual map */
1175  new_x = pl_pos.x+diff_x;
1176  new_y = pl_pos.y+diff_y;
1177 
1178  /* determine neccessary amount to shift */
1179 
1180  /* if(new_x < 1) is not possible: a big face may reach up to
1181  * (MAX_FACE_SIZE-1) tiles to the left of pl_pos. Therefore maintain a
1182  * border of at least MAX_FACE_SIZE to the left of the virtual map
1183  * edge.
1184  */
1185  if (new_x < MAX_FACE_SIZE) {
1186  shift_x = FOG_BORDER_MIN+MAX_FACE_SIZE-new_x;
1187  /* This yields: new_x+shift_x == FOG_BORDER_MIN+MAX_FACE_SIZE,
1188  * i.e. left border is FOG_BORDER_MIN+MAX_FACE_SIZE after
1189  * shifting.
1190  */
1191  } else if (new_x+MAX_VIEW > FOG_MAP_SIZE) {
1192  shift_x = FOG_MAP_SIZE-FOG_BORDER_MIN-MAX_VIEW-new_x;
1193  /* This yields: new_x+shift_x ==
1194  * FOG_MAP_SIZE-FOG_BODER_MIN-MAX_VIEW, i.e. right border is
1195  * FOGBORDER_MIN after shifting.
1196  */
1197  } else {
1198  shift_x = 0;
1199  }
1200 
1201  /* Same as above but for y. */
1202  if (new_y < MAX_FACE_SIZE) {
1203  shift_y = FOG_BORDER_MIN+MAX_FACE_SIZE-new_y;
1204  } else if (new_y+MAX_VIEW > FOG_MAP_SIZE) {
1205  shift_y = FOG_MAP_SIZE-FOG_BORDER_MIN-MAX_VIEW-new_y;
1206  } else {
1207  shift_y = 0;
1208  }
1209 
1210  /* No shift neccessary? ==> nothing to do. */
1211  if (shift_x == 0 && shift_y == 0) {
1212  return;
1213  }
1214 
1215  /* If shifting at all: maintain a border size of FOG_BORDER_MIN to all
1216  * directions. For example: if pl_pos=30/MAX_FACE_SIZE, and map_scroll is
1217  * 0/-1: shift pl_pos to FOG_BORDER_MIN+1/FOG_BORDER_MIN+1, not to
1218  * 30/FOG_BORDER_MIN+1.
1219  */
1220  if (shift_x == 0) {
1221  if (new_x < FOG_BORDER_MIN+MAX_FACE_SIZE) {
1222  shift_x = FOG_BORDER_MIN+MAX_FACE_SIZE-new_x;
1223  } else if (new_x+MAX_VIEW+FOG_BORDER_MIN > FOG_MAP_SIZE) {
1224  shift_x = FOG_MAP_SIZE-FOG_BORDER_MIN-MAX_VIEW-new_x;
1225  }
1226  }
1227  if (shift_y == 0) {
1228  if (new_y < FOG_BORDER_MIN+MAX_FACE_SIZE) {
1229  shift_y = FOG_BORDER_MIN+MAX_FACE_SIZE-new_y;
1230  } else if (new_y+MAX_VIEW+FOG_BORDER_MIN > FOG_MAP_SIZE) {
1231  shift_y = FOG_MAP_SIZE-FOG_BORDER_MIN-MAX_VIEW-new_y;
1232  }
1233  }
1234 
1235  /* Shift for more than virtual map size? ==> clear whole virtual map
1236  * and recenter.
1237  */
1238  if (shift_x <= -FOG_MAP_SIZE || shift_x >= FOG_MAP_SIZE
1239  || shift_y <= -FOG_MAP_SIZE || shift_y >= FOG_MAP_SIZE) {
1240  for (dx = 0; dx < FOG_MAP_SIZE; dx++) {
1241  clear_cells(dx, 0, FOG_MAP_SIZE);
1242  }
1243 
1244  pl_pos.x = FOG_MAP_SIZE/2-width/2;
1245  pl_pos.y = FOG_MAP_SIZE/2-height/2;
1246  return;
1247  }
1248 
1249  /* Move player position. */
1250  pl_pos.x += shift_x;
1251  pl_pos.y += shift_y;
1252 
1253  /* Actually shift the virtual map by shift_x/shift_y */
1254  if (shift_x < 0) {
1255  src_x = -shift_x;
1256  dst_x = 0;
1257  len_x = FOG_MAP_SIZE+shift_x;
1258  } else {
1259  src_x = 0;
1260  dst_x = shift_x;
1261  len_x = FOG_MAP_SIZE-shift_x;
1262  }
1263 
1264  if (shift_y < 0) {
1265  src_y = -shift_y;
1266  dst_y = 0;
1267  len_y = FOG_MAP_SIZE+shift_y;
1268  } else {
1269  src_y = 0;
1270  dst_y = shift_y;
1271  len_y = FOG_MAP_SIZE-shift_y;
1272  }
1273 
1274  if (shift_x < 0) {
1275  for (sx = src_x, dx = dst_x, i = 0; i < len_x; sx++, dx++, i++) {
1276  /* srcx!=dstx ==> can use memcpy since source and
1277  * destination to not overlap.
1278  */
1279  memcpy(&the_map.cells[dx][dst_y], &the_map.cells[sx][src_y], len_y*sizeof(the_map.cells[dx][dst_y]));
1280  }
1281  } else if (shift_x > 0) {
1282  for (sx = src_x+len_x-1, dx = dst_x+len_x-1, i = 0; i < len_x; sx--, dx--, i++) {
1283  /* srcx!=dstx ==> can use memcpy since source and
1284  * destination to not overlap.
1285  */
1286  memcpy(&the_map.cells[dx][dst_y], &the_map.cells[sx][src_y], len_y*sizeof(the_map.cells[dx][dst_y]));
1287  }
1288  } else {
1289  assert(src_x == dst_x);
1290  for (dx = src_x, i = 0; i < len_x; dx++, i++) {
1291  /* srcx==dstx ==> use memmove since source and
1292  * destination probably do overlap.
1293  */
1294  memmove(&the_map.cells[dx][dst_y], &the_map.cells[dx][src_y], len_y*sizeof(the_map.cells[dx][dst_y]));
1295  }
1296  }
1297 
1298  /* Clear newly opened area */
1299  for (dx = 0; dx < dst_x; dx++) {
1300  clear_cells(dx, 0, FOG_MAP_SIZE);
1301  }
1302  for (dx = dst_x+len_x; dx < FOG_MAP_SIZE; dx++) {
1303  clear_cells(dx, 0, FOG_MAP_SIZE);
1304  }
1305  if (shift_y > 0) {
1306  for (dx = 0; dx < len_x; dx++) {
1307  clear_cells(dx+dst_x, 0, shift_y);
1308  }
1309  } else if (shift_y < 0) {
1310  for (dx = 0; dx < len_x; dx++) {
1311  clear_cells(dx+dst_x, FOG_MAP_SIZE+shift_y, -shift_y);
1312  }
1313  }
1314 }
1315 
1320 static void mapdata_get_image_size(int face, guint8 *w, guint8 *h)
1321 {
1322  get_map_image_size(face, w, h);
1323  if (*w < 1) {
1324  *w = 1;
1325  }
1326  if (*h < 1) {
1327  *h = 1;
1328  }
1329  if (*w > MAX_FACE_SIZE) {
1330  *w = MAX_FACE_SIZE;
1331  }
1332  if (*h > MAX_FACE_SIZE) {
1333  *h = MAX_FACE_SIZE;
1334  }
1335 }
1336 
1337 /* This basically goes through all the map spaces and does the necessary
1338  * animation.
1339  */
1341 {
1342  int x, y, layer, face;
1343  struct MapCellLayer *cell;
1344 
1345 
1346  /* For synchronized animations, what we do is set the initial values
1347  * in the mapdata to the fields in the animations[] array. In this way,
1348  * the code below the iterates the spaces doesn't need to do anything
1349  * special. But we have to update the animations[] array here to
1350  * keep in sync.
1351  */
1352  for (x=0; x < MAXANIM; x++) {
1353  if (animations[x].speed) {
1354  animations[x].speed_left++;
1355  if (animations[x].speed_left >= animations[x].speed) {
1356  animations[x].speed_left=0;
1357  animations[x].phase++;
1358  if (animations[x].phase >= animations[x].num_animations) {
1359  animations[x].phase=0;
1360  }
1361  }
1362  }
1363  }
1364 
1365  for (x=0; x < CURRENT_MAX_VIEW; x++) {
1366  for (y=0; y < CURRENT_MAX_VIEW; y++) {
1367 
1368  /* Short cut some processing here. It makes sense to me
1369  * not to animate stuff out of view
1370  */
1371  if (the_map.cells[pl_pos.x + x][pl_pos.y + y].cleared) {
1372  continue;
1373  }
1374 
1375  for (layer=0; layer<MAXLAYERS; layer++) {
1376  /* Using the cell structure just makes life easier here */
1377  cell = &the_map.cells[pl_pos.x+x][pl_pos.y+y].heads[layer];
1378 
1379  if (cell->animation) {
1380  cell->animation_left++;
1381  if (cell->animation_left >= cell->animation_speed) {
1382  cell->animation_left=0;
1383  cell->animation_phase++;
1384  if (cell->animation_phase >= animations[cell->animation].num_animations) {
1385  cell->animation_phase=0;
1386  }
1387  face = animations[cell->animation].faces[cell->animation_phase];
1388 
1389  /* I don't think we send any to the client, but it is possible
1390  * for animations to have blank faces.
1391  */
1392  if (face >0) {
1393  expand_set_face(pl_pos.x + x, pl_pos.y + y, layer, face, FALSE);
1394  } else {
1395  expand_clear_face_from_layer(pl_pos.x + x, pl_pos.y + y , layer);
1396  }
1397  }
1398  }
1399  cell = &bigfaces[x][y][layer].head;
1400  if (cell->animation) {
1401  cell->animation_left++;
1402  if (cell->animation_left >= cell->animation_speed) {
1403  cell->animation_left=0;
1404  cell->animation_phase++;
1405  if (cell->animation_phase >= animations[cell->animation].num_animations) {
1406  cell->animation_phase=0;
1407  }
1408  face = animations[cell->animation].faces[cell->animation_phase];
1409 
1410  /* I don't think we send any to the client, but it is possible
1411  * for animations to have blank faces.
1412  */
1413  expand_set_bigface(x, y, layer, face, FALSE);
1414  }
1415  }
1416  }
1417  }
1418  }
1419 }
Animations animations[MAXANIM]
Definition: commands.c:1128
static int height
Definition: mapdata.c:82
int y
Definition: mapdata.h:67
gint16 mapdata_bigface(int x, int y, int layer, int *ww, int *hh)
Definition: mapdata.c:1053
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:1340
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
Definition: client.h:100
#define CONFIG_LIGHTING
Definition: client.h:201
#define CONFIG_DISPLAYMODE
Definition: client.h:194
Warning that something might not work.
Definition: client.h:443
struct MapCell * mapdata_cell(int x, int y)
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)
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)
Definition: mapdata.c:511
#define CFG_LT_PIXEL_BEST
Definition: client.h:231
#define ANIM_MASK
Definition: newclient.h:331
#define ANIM_FLAGS_MASK
Definition: newclient.h:325
static void mapdata_get_image_size(int face, guint8 *w, guint8 *h)
Definition: mapdata.c:1320
void mapdata_newmap(void)
Definition: mapdata.c:981
gint16 animation
Definition: mapdata.h:30
gint8 size_x
Definition: mapdata.h:20
#define CONFIG_MAPSCROLL
Definition: client.h:213
static void expand_need_update_from_layer(int x, int y, int layer)
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)
Definition: mapdata.c:1019
gint16 mapdata_bigface_head(int x, int y, int layer, int *ww, int *hh)
Definition: mapdata.c:1134
static void recenter_virtual_map_view(int diff_x, int diff_y)
Definition: mapdata.c:1163
static int width
Definition: mapdata.c:82
void LOG(LogLevel level, const char *origin, const char *format,...)
Definition: misc.c:109
guint16 x
Definition: mapdata.c:70
#define FOG_BORDER_MIN
Definition: mapdata.c:36
guint8 cleared
Definition: mapdata.h:58
static struct BigCell * bigfaces_head
Definition: mapdata.c:89
static void expand_set_bigface(int x, int y, int layer, gint16 face, int clear)
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
Definition: mapdata.c:30
void mapdata_size(int *x, int *y)
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)
Definition: mapdata.c:400
void mapdata_init(void)
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)
Definition: mapdata.c:1027
int x
Definition: mapdata.h:66
static void set_darkness(int x, int y, int darkness)
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)
Definition: mapdata.c:268
bool mapdata_contains(int x, int y)
Definition: mapdata.c:126
static void expand_clear_bigface(int x, int y, int w, int h, int layer, int set_need_update)
Definition: mapdata.c:346
#define ANIM_SYNC
Definition: newclient.h:323
Warning that something definitely didn't work.
Definition: client.h:444
static bool mapdata_has_tile(int x, int y, int layer)
Definition: mapdata.c:1002
guint8 animation_speed
Definition: mapdata.h:31
#define MAXLAYERS
Definition: mapdata.h:6
guint8 need_update
Definition: mapdata.h:55
void mapdata_scroll(int dx, int dy)
Definition: mapdata.c:908
static void clear_cells(int x, int y, int len_y)
Definition: mapdata.c:104
static void expand_set_face(int x, int y, int layer, gint16 face, int clear)
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)
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
#define MAX_VIEW
Definition: mapdata.h:11
#define MAX_FACE_SIZE
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]
Definition: mapdata.c:96
void mapdata_set_size(int viewx, int viewy)
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