Atrinik Server  4.0
world_maker.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
30 #include <global.h>
31 #include <loader.h>
32 #include <gd.h>
33 #include <toolkit/string.h>
34 #include <arch.h>
35 #include <toolkit/path.h>
36 
48 static int **wm_face_colors;
49 
51 #define MAX_PIXELS 3
52 
54 typedef struct wm_region {
55 
57  struct {
60 
62  int xpos;
63 
65  int ypos;
66  } *maps;
67 
69  size_t num_maps;
70 
72  int xpos;
73 
75  int ypos;
76 
79 
82 
84  int w;
85 
87  int h;
88 } wm_region;
89 
94 typedef struct region_map_def {
95  int xpos;
96  int ypos;
97  char *path;
98  char *regions;
100 
104 static int region_map_def_sort(const void *a, const void *b)
105 {
106  return strcmp(((const region_map_def_t *) a)->regions,
107  ((const region_map_def_t *) b)->regions);
108 }
109 
113 static void wm_images_init(void)
114 {
115  int i, x, y;
116  gdImagePtr im, im2;
117  uint8_t *data;
118  uint16_t len;
119 
120  wm_face_colors = emalloc(sizeof(*wm_face_colors) * nrofpixmaps);
121 
122  for (i = 0; i < nrofpixmaps; i++) {
123  uint64_t total = 0, r = 0, g = 0, b = 0;
124 
125  /* Get the face's data. */
126  face_get_data(i, &data, &len);
127 
128  /* Create the image from the data. */
129  im = gdImageCreateFromPngPtr(len, data);
130  gdImageAlphaBlending(im, 1);
131  gdImageSaveAlpha(im, 1);
132 
133  im2 = gdImageCreateTrueColor(im->sx, im->sy);
134  gdImageCopyResized(im2, im, 0, 0, 0, 0, im2->sx, im2->sy, im->sx,
135  im->sy);
136 
137  wm_face_colors[i] = ecalloc(1, sizeof(**wm_face_colors) * 5);
138 
139  /* Get the average pixel colors. */
140  for (x = 0; x < im2->sx; x++) {
141  for (y = 0; y < im2->sy; y++) {
142  int color = gdImageGetPixel(im2, x, y);
143 
144  if (color) {
145  r += gdImageRed(im2, color);
146  g += gdImageGreen(im2, color);
147  b += gdImageBlue(im2, color);
148  total++;
149  }
150  }
151  }
152 
153  /* Store the total. */
154  if (total) {
155  r /= total;
156  g /= total;
157  b /= total;
158  wm_face_colors[i][0] = gdImageColorResolve(im2, r, g, b);
159  wm_face_colors[i][1] = gdImageColorResolve(im2, MIN(r + 10, 255),
160  MIN(g + 10, 255),
161  MIN(b + 10, 255));
162  wm_face_colors[i][2] = r;
163  wm_face_colors[i][3] = g;
164  wm_face_colors[i][4] = b;
165  }
166 
167  gdImageDestroy(im);
168  gdImageDestroy(im2);
169  }
170 }
171 
175 static void wm_images_deinit(void)
176 {
177  for (int i = 0; i < nrofpixmaps; i++) {
178  efree(wm_face_colors[i]);
179  }
180 
181  efree(wm_face_colors);
182 }
183 
197 static int render_object(gdImagePtr im, int x, int y, object *ob)
198 {
199  object *head, *tmp;
200  int i, color, r, g, b, num, j, start, max, k, mx, my, z, num_z;
201  mapstruct *m;
202 
203  /* Sanity check. */
204  if (ob == NULL) {
205  return 0;
206  }
207 
208  head = HEAD(ob);
209 
210  /* Do not render system objects. */
211  if (QUERY_FLAG(head, FLAG_SYS_OBJECT)) {
212  return 0;
213  }
214 
215  /* Only render the following objects:
216  * - floor (the terrain, obviously)
217  * - walls
218  * - doors
219  * - exits (stairs, but also useful to see portals)
220  * - shop mats
221  * - holy altars
222  * - signs
223  * - misc objects blocking passage (rocks, trees, etc)
224  */
225  if (head->layer != LAYER_FLOOR &&
226  (head->type != WALL || QUERY_FLAG(head, FLAG_DRAW_DIRECTION)) &&
227  head->type != DOOR &&
228  head->type != EXIT &&
229  head->type != HOLY_ALTAR &&
230  head->type != SIGN &&
231  (head->type != MISC_OBJECT || !QUERY_FLAG(head, FLAG_NO_PASS))) {
232  return 0;
233  }
234 
235  /* No image, so we don't want to render anything, and only check whether
236  * the object is renderable. */
237  if (im == NULL) {
238  return 1;
239  }
240 
241  for (i = 0; i <= SIZEOFFREE1; i++) {
242  color = wm_face_colors[head->face->number][0];
243  r = wm_face_colors[head->face->number][2];
244  g = wm_face_colors[head->face->number][3];
245  b = wm_face_colors[head->face->number][4];
246  z = 0;
247  num = 1;
248  num_z = 0;
249 
250  if (i > 0) {
251  start = i - ((i - 1) % 2);
252  max = i + ((i - 1) % 2);
253 
254  /* Try to look for objects on adjacent tiles for a smoother
255  * color transition. */
256  for (j = start; j <= max; j++) {
257  k = (((j + SIZEOFFREE1) - 1) % SIZEOFFREE1) + 1;
258 
259  mx = ob->x + freearr_x[k];
260  my = ob->y + freearr_y[k];
261 
262  m = get_map_from_coord(ob->map, &mx, &my);
263 
264  if (m == NULL) {
265  continue;
266  }
267 
268  tmp = GET_MAP_OB_LAYER(m, mx, my, LAYER_WALL, 0);
269 
270  if (tmp != NULL && tmp->type == WALL) {
271  continue;
272  }
273 
274  /* Try to find something renderable on the adjacent tile,
275  * that has the same layer as the object being rendered. */
276  for (tmp = GET_MAP_OB_LAST(m, mx, my); tmp != NULL;
277  tmp = tmp->below) {
278  if (tmp->layer == head->layer) {
279  break;
280  }
281  }
282 
283  if (tmp == NULL) {
284  /* Didn't find anything on the same layer and sub-layer,
285  * so try to find anything at all that is renderable. */
286  for (tmp = GET_MAP_OB_LAST(m, mx, my); tmp != NULL;
287  tmp = tmp->below) {
288  if (render_object(NULL, 0, 0, tmp)) {
289  break;
290  }
291  }
292 
293  /* If there's nothing on this tile, increase num for
294  * a smoother transition to black. */
295  if (tmp == NULL) {
296  num++;
297  continue;
298  }
299  }
300 
301  tmp = HEAD(tmp);
302 
303  if (tmp == head) {
304  continue;
305  }
306 
307  if (tmp->type == FLOOR && tmp->z != 0) {
308  z += tmp->z;
309  num_z++;
310  }
311 
312  r += wm_face_colors[tmp->face->number][2];
313  g += wm_face_colors[tmp->face->number][3];
314  b += wm_face_colors[tmp->face->number][4];
315  num++;
316  }
317  }
318 
319  if (num != 1) {
320  r /= num;
321  g /= num;
322  b /= num;
323 
324  if (r != wm_face_colors[head->face->number][2] ||
325  g != wm_face_colors[head->face->number][3] ||
326  b != wm_face_colors[head->face->number][4]) {
327  color = -1;
328  }
329  }
330 
331  if (head->type == FLOOR && head->z != 0) {
332  z += head->z;
333  num_z++;
334  }
335 
336  if (num_z != 0) {
337  r -= z / (double) num_z / 2.5;
338  g -= z / (double) num_z / 2.5;
339  b -= z / (double) num_z / 2.5;
340  color = -1;
341  }
342 
343  if (color == -1) {
344  r = MAX(0, MIN(255, r));
345  g = MAX(0, MIN(255, g));
346  b = MAX(0, MIN(255, b));
347  color = gdImageColorResolve(im, r, g, b);
348  }
349 
350  gdImageSetPixel(im, x + 1 + freearr_x[i], y + 1 + freearr_y[i],
351  color);
352  }
353 
354  return 1;
355 }
356 
364 static void region_add_map(wm_region *r, mapstruct *m)
365 {
366  /* Resize the array. */
367  r->maps = erealloc(r->maps, sizeof(*r->maps) * (r->num_maps + 1));
368  r->maps[r->num_maps].m = m;
369  r->maps[r->num_maps].xpos = r->xpos;
370  r->maps[r->num_maps].ypos = r->ypos;
371  r->num_maps++;
372 }
373 
384 static int map_in_region(mapstruct *m, const char *name)
385 {
386  region_struct *r;
387 
388  for (r = m->region; r; r = r->parent) {
389  if (!strcmp(r->name, name)) {
390  return 1;
391  }
392  }
393 
394  return 0;
395 }
396 
406 static void region_add_rec(wm_region *r, mapstruct *m, const char *region_name)
407 {
408  int i;
409 
410  region_add_map(r, m);
411 
412  /* Going through 4 tile paths should be enough. */
413  for (i = 0; i < 4; i++) {
414  /* No such tile path. */
415  if (!m->tile_path[i]) {
416  continue;
417  }
418 
419  /* Load the map if needed. */
420  if (!m->tile_map[i]) {
421  m->tile_map[i] = ready_map_name(m->tile_path[i], NULL,
423 
424  if (!m->tile_map[i]) {
425  continue;
426  }
427  }
428 
429  /* If there is a map and it wasn't traversed yet... */
430  if (m->tile_map[i] && !m->tile_map[i]->traversed) {
431  m->tile_map[i]->traversed = 1;
432 
433  /* Is the map in region? */
434  if (map_in_region(m->tile_map[i], region_name)) {
435  switch (i) {
436  case 0:
437  r->ypos -= MAP_HEIGHT(m->tile_map[i]) * MAX_PIXELS;
438  break;
439 
440  case 1:
441  r->xpos += MAP_WIDTH(m->tile_map[i]) * MAX_PIXELS;
442  break;
443 
444  case 2:
445  r->ypos += MAP_HEIGHT(m->tile_map[i]) * MAX_PIXELS;
446  break;
447 
448  case 3:
449  r->xpos -= MAP_WIDTH(m->tile_map[i]) * MAX_PIXELS;
450  break;
451  }
452 
453  /* Store the lowest x/y positions to do adjustments later. */
454  if (r->xpos < r->xpos_lowest) {
455  r->xpos_lowest = r->xpos;
456  }
457 
458  if (r->ypos < r->ypos_lowest) {
459  r->ypos_lowest = r->ypos;
460  }
461 
462  /* Go on recursively. */
463  region_add_rec(r, m->tile_map[i], region_name);
464 
465  switch (i) {
466  case 0:
467  r->ypos += MAP_HEIGHT(m->tile_map[i]) * MAX_PIXELS;
468  break;
469 
470  case 1:
471  r->xpos -= MAP_WIDTH(m->tile_map[i]) * MAX_PIXELS;
472  break;
473 
474  case 2:
475  r->ypos -= MAP_HEIGHT(m->tile_map[i]) * MAX_PIXELS;
476  break;
477 
478  case 3:
479  r->xpos += MAP_WIDTH(m->tile_map[i]) * MAX_PIXELS;
480  break;
481  }
482  }
483  }
484  }
485 }
486 
490 void world_maker(void)
491 {
492  mapstruct *m;
493  gdImagePtr im;
494  FILE *out;
495  size_t i;
496  region_struct *r, *r2;
497  wm_region *wm_r;
498  char buf[MAX_BUF];
499  int x, y, layer, sub_layer, got_one;
500  int xpos = 0, ypos = 0;
501  FILE *def_fp;
502  object **info_objects = NULL;
503  size_t num_info_objects = 0;
504  UT_icd icd = {sizeof(region_map_def_t), NULL, NULL, NULL};
505  UT_array *def_maps;
506  region_map_def_t def_map, *def_map_curr, *def_map_prev;
507  StringBuffer *sb;
508 
509  /* Initialize the image colors. */
510  wm_images_init();
511 
512  /* Go through regions. */
513  for (r = first_region; r; r = r->next) {
514  /* No first map? */
515  if (!r->map_first) {
516  continue;
517  }
518 
519  /* Initialize the region. */
520  wm_r = ecalloc(1, sizeof(wm_region));
521  /* Open the definitions file. */
522  snprintf(VS(buf), "%s/client-maps/%s.def", settings.httppath, r->name);
523  path_ensure_directories(buf);
524 
525  def_fp = fopen(buf, "w");
526 
527  if (!def_fp) {
528  LOG(ERROR, "Could not open '%s': %s", buf,
529  strerror(errno));
530  exit(1);
531  }
532 
533  /* Load the first map. */
534  m = ready_map_name(r->map_first, NULL, MAP_NO_DYNAMIC);
535  /* Parse the maps recursively. */
536  region_add_rec(wm_r, m, r->name);
537 
538  snprintf(VS(buf), "%s/client-maps/%s.png", settings.httppath, r->name);
539  path_ensure_directories(buf);
540 
541  /* Store defaults in the definitions file. */
542  fprintf(def_fp, "pixel_size %d\n", MAX_PIXELS);
543  fprintf(def_fp, "map_size_x %d\n", MAP_WIDTH(m));
544  fprintf(def_fp, "map_size_y %d\n", MAP_HEIGHT(m));
545 
546  utarray_new(def_maps, &icd);
547 
548  /* Go through the loaded maps. */
549  for (i = 0; i < wm_r->num_maps; i++) {
550  int map_w, map_h;
551 
552  /* Adjust X and Y positions. */
553  wm_r->maps[i].xpos -= wm_r->xpos_lowest;
554  wm_r->maps[i].ypos -= wm_r->ypos_lowest;
555 
556  /* Calculate the maximum width needed for the actual image. */
557  map_w = MAP_WIDTH(wm_r->maps[i].m) * MAX_PIXELS +
558  wm_r->maps[i].xpos;
559  map_h = MAP_HEIGHT(wm_r->maps[i].m) * MAX_PIXELS +
560  wm_r->maps[i].ypos;
561 
562  if (map_w > wm_r->w) {
563  wm_r->w = map_w;
564  }
565 
566  if (map_h > wm_r->h) {
567  wm_r->h = map_h;
568  }
569 
570  /* Store the map path, labels, etc. */
571  for (m = wm_r->maps[i].m; m != NULL; m = get_map_from_tiled(m,
572  TILED_UP)) {
573  if (m->region != wm_r->maps[i].m->region) {
574  break;
575  }
576 
577  sb = stringbuffer_new();
578 
579  for (r2 = m->region; r2 != NULL; r2 = r2->parent) {
580  if (r2 != m->region && !r2->child_maps) {
581  continue;
582  }
583 
584  if (stringbuffer_length(sb) != 0) {
585  stringbuffer_append_char(sb, ',');
586  }
587 
588  stringbuffer_append_string(sb, r2->name);
589  }
590 
591  def_map.xpos = wm_r->maps[i].xpos;
592  def_map.ypos = wm_r->maps[i].ypos;
593  def_map.path = estrdup(m->path);
594  def_map.regions = stringbuffer_finish(sb);
595  utarray_push_back(def_maps, &def_map);
596  }
597  }
598 
599  utarray_sort(def_maps, region_map_def_sort);
600 
601  def_map_prev = NULL;
602 
603  for (i = 0; i < utarray_len(def_maps); i++) {
604  def_map_curr = (region_map_def_t *) utarray_eltptr(def_maps, i);
605  fprintf(def_fp, "map %x %x %s", def_map_curr->xpos,
606  def_map_curr->ypos, def_map_curr->path);
607 
608  if (def_map_prev == NULL || strcmp(def_map_curr->regions,
609  def_map_prev->regions) != 0) {
610  fprintf(def_fp, " %s", def_map_curr->regions);
611  }
612 
613  fprintf(def_fp, "\n");
614 
615  def_map_prev = def_map_curr;
616  }
617 
618  for (i = 0; i < utarray_len(def_maps); i++) {
619  def_map_curr = (region_map_def_t *) utarray_eltptr(def_maps, i);
620  efree(def_map_curr->path);
621  efree(def_map_curr->regions);
622  }
623 
624  utarray_free(def_maps);
625 
626  /* Create the image. */
627  im = gdImageCreateTrueColor(wm_r->w, wm_r->h);
628  gdImageAlphaBlending(im, 1);
629 
630  /* Custom background to use? */
631  if (r->map_bg) {
632  uint32_t im_r, im_g, im_b;
633 
634  /* Parse HTML color and fill the image with it. */
635  if (sscanf(r->map_bg, "#%2X%2X%2X", &im_r, &im_g, &im_b) == 3) {
636  gdImageFill(im, 0, 0,
637  gdImageColorAllocate(im, im_r, im_g, im_b));
638  }
639  } else {
640  /* Transparency otherwise. */
641  gdImageSaveAlpha(im, 1);
642  gdImageFill(im, 0, 0, gdTransparent);
643  }
644 
645  /* Go through the maps. */
646  for (i = 0; i < wm_r->num_maps; i++) {
647  object *tmp;
648 
649  m = wm_r->maps[i].m;
650 
651  /* Draw layer 1 and layer 2 objects. */
652  for (x = 0; x < MAP_WIDTH(m); x++) {
653  for (y = 0; y < MAP_HEIGHT(m); y++) {
654  got_one = 0;
655  xpos = x * MAX_PIXELS + wm_r->maps[i].xpos;
656  ypos = y * MAX_PIXELS + wm_r->maps[i].ypos;
657 
658  /* Look for map info objects. */
659  for (tmp = GET_MAP_OB(m, x, y);
660  tmp && tmp->layer == LAYER_SYS;
661  tmp = tmp->above) {
662  if (tmp->type != CLIENT_MAP_INFO) {
663  continue;
664  }
665 
666  if (tmp->sub_type != CLIENT_MAP_HIDE && (!tmp->name ||
667  strstr(tmp->name, " ") ||
668  !strcmp(tmp->name, tmp->arch->name))) {
669  continue;
670  }
671 
672  /* Transform newline characters in the message to
673  * literal "\n". */
674  if (tmp->msg) {
675  char msg[HUGE_BUF * 4];
676 
677  string_replace(tmp->msg, "\n", "\\n", msg,
678  sizeof(msg));
679  FREE_AND_COPY_HASH(tmp->msg, msg);
680  }
681 
682  /* Label. */
683  if (tmp->sub_type == CLIENT_MAP_LABEL) {
684  fprintf(def_fp, "label %x %x %s %s\n",
685  xpos + tmp->last_heal * MAX_PIXELS,
686  ypos + tmp->last_sp * MAX_PIXELS,
687  tmp->name, tmp->msg ? tmp->msg : "???");
688 
689  if (QUERY_FLAG(tmp, FLAG_CURSED)) {
690  fprintf(def_fp, "label_hide\n");
691  }
692  } else {
693  info_objects = erealloc(
694  info_objects,
695  sizeof(*info_objects) * (num_info_objects + 1)
696  );
697  info_objects[num_info_objects] = tmp;
698  num_info_objects++;
699  }
700  }
701 
702  for (layer = LAYER_FLOOR;
703  layer <= LAYER_FMASK;
704  layer++) {
705  for (sub_layer = 0;
706  sub_layer < NUM_SUB_LAYERS;
707  sub_layer++) {
708  if (render_object(
709  im, xpos, ypos,
710  GET_MAP_OB_LAYER(m, x, y, layer, sub_layer)
711  )) {
712  got_one = 1;
713  }
714  }
715  }
716 
717  /* Didn't get an object, fill this square with black. */
718  if (!got_one) {
719  gdImageFilledRectangle(
720  im, xpos, ypos,
721  xpos + MAX_PIXELS - 1,
722  ypos + MAX_PIXELS - 1,
723  gdImageColorAllocate(im, 0, 0, 0)
724  );
725  }
726  }
727  }
728 
729  /* Draw the rest of the objects. */
730  for (x = 0; x < MAP_WIDTH(m); x++) {
731  for (y = 0; y < MAP_HEIGHT(m); y++) {
732  xpos = x * MAX_PIXELS + wm_r->maps[i].xpos;
733  ypos = y * MAX_PIXELS + wm_r->maps[i].ypos;
734 
735  for (layer = LAYER_ITEM;
736  layer <= NUM_LAYERS;
737  layer++) {
738  for (sub_layer = 0;
739  sub_layer < NUM_SUB_LAYERS;
740  sub_layer++) {
742  im, xpos, ypos,
743  GET_MAP_OB_LAYER(m, x, y, layer, sub_layer)
744  );
745  }
746  }
747  }
748  }
749  }
750 
751  /* Parse other information objects. */
752  for (i = 0; i < num_info_objects; i++) {
753  object *tmp = info_objects[i];
754  size_t j;
755 
756  /* Already parsed this object. */
757  if (!tmp) {
758  continue;
759  }
760 
761  /* Get the correct X/Y positions. */
762  for (j = 0; j < wm_r->num_maps; j++) {
763  if (wm_r->maps[j].m == tmp->map) {
764  xpos = tmp->x * MAX_PIXELS + wm_r->maps[j].xpos;
765  ypos = tmp->y * MAX_PIXELS + wm_r->maps[j].ypos;
766  break;
767  }
768  }
769 
770  /* Hiding part of the map. */
771  if (tmp->sub_type == CLIENT_MAP_HIDE) {
772  gdImageFilledRectangle(
773  im, xpos, ypos,
774  MIN(xpos + ((tmp->path_attuned + 1) * MAX_PIXELS),
775  (uint32_t) wm_r->w),
776  MIN(ypos + ((tmp->path_repelled + 1) * MAX_PIXELS),
777  (uint32_t) wm_r->h),
778  gdImageColorAllocate(im, 0, 0, 0)
779  );
780  }
781 
782  /* Tooltip. */
783  if (tmp->msg && tmp->sub_type == CLIENT_MAP_TOOLTIP) {
784  /* Tooltip with automatic width/height detection? */
785  if (!tmp->path_attuned &&
786  !tmp->path_repelled &&
787  !tmp->item_level &&
789  for (j = 0; j < num_info_objects; j++) {
790  rv_vector rv;
791 
792  /* Already parsed object or same as the master info
793  * object. */
794  if (!info_objects[j] || info_objects[j] == tmp) {
795  continue;
796  }
797 
798  /* Not the same name as the master info object? */
799  if (strcmp(info_objects[j]->name, tmp->name)) {
800  continue;
801  }
802 
803  /* Get range vector from the master info object to this
804  * one. */
805  if (!get_rangevector(tmp, info_objects[j], &rv,
807  continue;
808  }
809 
810  /* Set the calculated distances. */
811  if (!tmp->path_attuned) {
812  tmp->path_attuned = rv.distance_x;
813  }
814 
815  if (!tmp->path_repelled) {
816  tmp->path_repelled = rv.distance_y;
817  }
818 
819  /* Mark this object as parsed. */
820  info_objects[j] = NULL;
821  }
822  }
823 
824  /* Write out information about this tooltip. */
825  fprintf(def_fp, "tooltip %x %x %x %x %s %s\n",
826  MAX(0, xpos - ((tmp->item_level) * MAX_PIXELS)),
827  MAX(0, ypos - ((tmp->item_level) * MAX_PIXELS)),
828  MIN(xpos + ((tmp->item_level * 2) * MAX_PIXELS +
829  MAX_PIXELS) + (tmp->path_attuned * MAX_PIXELS),
830  (uint32_t) wm_r->w
831  ) - xpos,
832  MIN(ypos + ((tmp->item_level * 2) * MAX_PIXELS +
833  MAX_PIXELS) + (tmp->path_repelled * MAX_PIXELS),
834  (uint32_t) wm_r->h
835  ) - ypos,
836  tmp->name, tmp->msg);
837 
838  /* Outline set? */
839  if (tmp->item_skill) {
840  fprintf(def_fp, "t_outline");
841 
842  /* Store outline's color, if any. */
843  if (tmp->slaying) {
844  fprintf(def_fp, " %s", tmp->slaying);
845  } else if (tmp->item_skill != 1) {
846  /* No outline color, but there is non-standard size,
847  * so we must include the default color as well. */
848  fprintf(def_fp, " #ff0000");
849  }
850 
851  if (tmp->item_skill != 1) {
852  fprintf(def_fp, " %d", tmp->item_skill);
853  }
854 
855  fprintf(def_fp, "\n");
856  }
857 
858  if (QUERY_FLAG(tmp, FLAG_CURSED)) {
859  fprintf(def_fp, "tooltip_hide\n");
860  }
861  }
862  }
863 
864  if (info_objects) {
865  efree(info_objects);
866  info_objects = NULL;
867  }
868 
869  num_info_objects = 0;
870 
871  /* Free all maps to save memory. */
872  free_all_maps();
873 
874  /* Write out the image. */
875  out = fopen(buf, "wb");
876 
877  if (out == NULL) {
878  LOG(ERROR, "Could not open '%s': %s", buf,
879  strerror(errno));
880  exit(1);
881  }
882 
883  gdImagePng(im, out);
884  fclose(out);
885 
886  /* Free data. */
887  gdImageDestroy(im);
888  fclose(def_fp);
889  efree(wm_r->maps);
890  efree(wm_r);
891  }
892 
894 }
#define FREE_AND_COPY_HASH(_sv_, _nv_)
Definition: global.h:100
uint32_t traversed
Definition: map.h:630
#define EXIT
Definition: define.h:312
struct wm_region::@8 * maps
uint8_t item_level
Definition: object.h:375
int get_rangevector(object *op1, object *op2, rv_vector *retval, int flags)
Definition: map.c:2238
#define FLAG_SYS_OBJECT
Definition: define.h:1243
#define FLAG_CURSED
Definition: define.h:1154
struct region_struct * next
Definition: map.h:453
static void wm_images_deinit(void)
Definition: world_maker.c:175
#define LAYER_FMASK
Definition: map.h:51
int xpos_lowest
Definition: world_maker.c:78
int ypos
Y position of the map.
Definition: world_maker.c:96
char * map_bg
Definition: map.h:490
#define TILED_UP
Definition: global.h:203
#define MAP_WIDTH(m)
Definition: map.h:120
shstr * path
Definition: map.h:568
mapstruct * get_map_from_coord(mapstruct *m, int *x, int *y)
Definition: map.c:1869
#define SIZEOFFREE1
Definition: define.h:654
int16_t last_heal
Definition: object.h:310
uint8_t item_skill
Definition: object.h:378
int distance_x
Definition: map.h:778
#define MAX_PIXELS
Definition: world_maker.c:51
char httppath[MAX_BUF]
Definition: global.h:353
char * path
Map path.
Definition: world_maker.c:97
const char * slaying
Definition: object.h:180
int16_t last_sp
Definition: object.h:313
#define HOLY_ALTAR
Definition: define.h:288
#define LAYER_FLOOR
Definition: map.h:49
#define CLIENT_MAP_INFO
Definition: define.h:526
#define LAYER_ITEM
Definition: map.h:53
uint8_t layer
Definition: object.h:405
#define MISC_OBJECT
Definition: define.h:349
struct obj * above
Definition: object.h:120
int ypos_lowest
Definition: world_maker.c:81
region_struct * first_region
Definition: region.c:37
uint32_t path_attuned
Definition: object.h:255
static void wm_images_init(void)
Definition: world_maker.c:113
#define QUERY_FLAG(xyz, p)
Definition: define.h:761
uint32_t path_repelled
Definition: object.h:258
struct archetype * arch
Definition: object.h:225
void world_maker(void)
Definition: world_maker.c:490
#define FLAG_STAND_STILL
Definition: define.h:1133
#define WALL
Definition: define.h:340
#define FLAG_DRAW_DIRECTION
Definition: define.h:1326
#define LAYER_SYS
Definition: map.h:47
uint16_t number
Definition: face.h:46
int distance_y
Definition: map.h:781
struct wm_region wm_region
int16_t y
Definition: object.h:276
#define CLIENT_MAP_HIDE
Definition: define.h:628
#define CLIENT_MAP_TOOLTIP
Definition: define.h:626
static int map_in_region(mapstruct *m, const char *name)
Definition: world_maker.c:384
struct region_struct * parent
Definition: map.h:460
#define RV_RECURSIVE_SEARCH
Definition: map.h:825
int16_t z
Definition: object.h:286
struct mapdef * map
Definition: object.h:139
static void region_add_rec(wm_region *r, mapstruct *m, const char *region_name)
Definition: world_maker.c:406
size_t num_maps
Definition: world_maker.c:69
union @21 data
Data about the rule.
void free_all_maps(void)
Definition: map.c:1677
const char * name
Definition: object.h:168
shstr * tile_path[TILED_NUM]
Definition: map.h:571
struct obj * below
Definition: object.h:114
struct mapdef * tile_map[TILED_NUM]
Definition: map.h:550
#define MAP_HEIGHT(m)
Definition: map.h:122
static int ** wm_face_colors
Definition: world_maker.c:48
#define NUM_LAYERS
Definition: map.h:67
uint64_t num
Number of successful updates.
Definition: metaserver.c:43
bool child_maps
If true, map of this region has all the children.
Definition: map.h:498
#define SIGN
Definition: define.h:409
#define HEAD(op)
Definition: object.h:657
#define MAP_NO_DYNAMIC
Definition: map.h:161
char * map_first
Definition: map.h:487
int16_t x
Definition: object.h:273
#define NUM_SUB_LAYERS
Definition: map.h:71
struct settings_struct settings
Definition: init.c:55
#define MAP_NAME_SHARED
Definition: map.h:157
#define FLOOR
Definition: define.h:324
static void region_add_map(wm_region *r, mapstruct *m)
Definition: world_maker.c:364
void face_get_data(int face, uint8_t **ptr, uint16_t *len)
Definition: image.c:272
region_struct * region
Definition: map.h:580
static int region_map_def_sort(const void *a, const void *b)
Definition: world_maker.c:104
int freearr_x[SIZEOFFREE]
Definition: object.c:84
uint8_t type
Definition: object.h:360
int xpos
X position of the map.
Definition: world_maker.c:95
shstr * name
More definite name, like "kobold".
Definition: arch.h:46
char * regions
Comma-separated list of all regions this map belongs to.
Definition: world_maker.c:98
const char * msg
Definition: object.h:183
char * name
Definition: map.h:463
#define CLIENT_MAP_LABEL
Definition: define.h:624
mapstruct * m
Definition: world_maker.c:59
#define DOOR
Definition: define.h:194
static int render_object(gdImagePtr im, int x, int y, object *ob)
Definition: world_maker.c:197
#define FLAG_NO_PASS
Definition: define.h:908
mapstruct * ready_map_name(const char *name, mapstruct *originator, int flags)
Definition: map.c:1584
int nrofpixmaps
Definition: image.c:67
Definition: map.h:536
New_Face * face
Definition: object.h:234
int freearr_y[SIZEOFFREE]
Definition: object.c:99
mapstruct * get_map_from_tiled(mapstruct *m, int tiled)
Definition: map.c:1838
#define LAYER_WALL
Definition: map.h:57
struct region_map_def region_map_def_t
uint8_t sub_type
Definition: object.h:363