Crossfire Server, Trunk  1.75.0
mapper.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire map browser generator.
3  *
4  * Author: Nicolas Weeger <nicolas.weeger@laposte.net>, (C) 2006-2021.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
180 #include <ctype.h>
181 #include <errno.h>
182 #include <stdio.h>
183 #include <stdlib.h>
184 #include <string.h>
185 #include <strings.h>
186 #include <sys/stat.h>
187 #include <sys/types.h>
188 #include <time.h>
189 
190 #include "global.h"
191 #include "sproto.h"
192 #include "image.h"
193 #include "quest.h"
194 
195 extern "C" {
196 #include <gd.h>
197 #include <gdfonts.h>
198 #include <gdfontl.h>
199 #include <gdfontg.h>
200 }
201 
202 #include "inja.hpp"
203 #include <map>
204 #include <set>
205 
206 static std::vector<gdImagePtr> gdfaces;
207 
210  const char *name;
211  const char *message;
212  int x, y;
213 };
214 
216 typedef std::vector<struct_npc_info *> npc_list;
217 
220  struct struct_race **races;
221  size_t count;
222  size_t allocated;
223 };
224 
228  size_t count;
229  size_t allocated;
230 };
231 
235  size_t count;
236  size_t allocated;
237 };
238 
241  char *path;
242  char *name;
243  char *filename;
244  char *lore;
251 
253 
255 
258 
260  int height, width;
262  struct struct_map_info *tiles[4];
263 };
264 
267 
270 
273  char *name;
274  int power;
276  char *diff;
278 };
279 
280 static std::vector<struct_equipment *> special_equipment;
284 struct struct_race {
285  char *name;
286  int count;
288 };
289 
292 static std::set<std::string> reset_groups;
295 enum class SearchType {
296  Region = 1,
297  Map,
298  Item,
299  Monster,
300  Quest,
301  Count
302 };
303 
305 static std::string SearchName[int(SearchType::Count)] = {
306  "(invalid)",
307  "region",
308  "map",
309  "item",
310  "monster",
311  "quest",
312 };
313 
320  list->races = NULL;
321  list->count = 0;
322  list->allocated = 0;
323 }
324 
335 static void add_race_to_list(struct_race *race, struct_race_list *list, int check) {
336  if (check) {
337  size_t test;
338 
339  for (test = 0; test < list->count; test++) {
340  if (list->races[test] == race)
341  return;
342  }
343  }
344 
345  if (list->allocated == list->count) {
346  list->allocated += 50;
347  list->races = (struct_race **)realloc(list->races, sizeof(struct_race *)*list->allocated);
348  }
349  list->races[list->count] = race;
350  list->count++;
351 }
352 
354 static char root[500];
355 
357 static int pics_allocated;
358 
359 /* Options */
360 static int generate_pics = 1;
361 static int force_pics = 0;
362 static int sizes[] = {32, 16, 8, 4, 2};
363 static const int num_sizes = sizeof(sizes)/sizeof(int);
364 #define size_large sizes[0]
365 #define size_small sizes[1]
366 static int map_limit = -1;
367 static int show_maps = 0;
368 static int world_map = 1;
369 static int world_exit_info = 1;
370 static int tileset = 0;
371 static bool detail_quests = false;
372 static bool list_system_quests = false;
373 static bool display_rendered_template = false;
374 static bool build_search_file = false;
377 static int created_pics = 0;
378 static int cached_pics = 0;
382  OF_PNG = 0,
383  OF_JPG = 1
384 };
385 
387 static const char *output_extensions[] = {
388  ".png",
389  ".jpg"
390 };
391 
394 
396 static int jpeg_quality = -1;
397 
399 static int rawmaps = 0;
400 
402 static int warn_no_path = 0;
403 
408  int sum_x, sum_y, sum;
409  int is_world;
410 };
411 
412 static struct struct_region_info **regions = NULL;
413 static size_t region_count = 0;
414 static size_t region_allocated = 0;
416 static int list_unused_maps = 0;
417 static std::vector<char *> found_maps;
419 /* Path/exit info */
420 static gdImagePtr infomap;
422 static int color_linked_exit;
423 static int color_road;
424 static int color_blocking;
425 static int color_slowing;
427 static int **elevation_info;
428 static int elevation_min;
429 static int elevation_max;
431 /* Whether to compute links between regions or not (expensive). */
432 static bool do_regions_link = false;
433 /* Links between regions, key is source, value are destinations. */
434 static std::map<region *, std::set<region *>> region_links;
435 
437 #define S_DOOR 0
438 #define S_KEY 1
439 #define S_CONTAINER 2
440 #define S_DETECTOR 3
441 #define S_CONNECT 4
442 #define S_MAX 5
443 
446  char *slaying;
448 };
449 
451 static size_t slaying_count = 0;
452 static size_t slaying_allocated = 0;
460  list->maps = NULL;
461  list->count = 0;
462  list->allocated = 0;
463 }
464 
465 static void add_map(struct_map_info *info, struct_map_list *list);
466 
467 static int is_special_equipment(object *item) {
468  if (item->name == item->arch->clone.name && item->title == item->arch->clone.title)
469  return 0;
470  if (QUERY_FLAG(item, FLAG_NO_PICK))
471  return 0;
472  if (item->move_block == MOVE_ALL)
473  return 0;
474 
475  if (IS_SHIELD(item) || IS_WEAPON(item) || IS_ARMOR(item) || IS_ARROW(item) || (item->type == ROD) || (item->type == WAND) || (item->type == RING) || (item->type == AMULET))
476  return 1;
477 
478  return 0;
479 }
480 
487  struct_equipment *add = (struct_equipment *)calloc(1, sizeof(struct_equipment));
488 
489  init_map_list(&add->origin);
490  return add;
491 }
492 
499 static void free_equipment(struct_equipment *equip) {
500  free(equip->diff);
501  free(equip->name);
502  free(equip);
503 }
504 
513 static bool sort_equipment(const struct_equipment *l, const struct_equipment *r) {
514  int cmp = strcasecmp(l->name, r->name);
515  if (cmp)
516  return cmp < 0;
517  if (l->power != r->power)
518  return l->power < r->power;
519  if (l->calc_power != r->calc_power)
520  return l->calc_power < r->calc_power;
521 
522  return strcasecmp(l->diff, r->diff) < 0;
523 }
524 
534  assert(item);
535  auto existing = std::find_if(special_equipment.begin(), special_equipment.end(),
536  [&] (const auto *e) { return !sort_equipment(e, item) && !sort_equipment(item, e); });
537 
538  if (existing != special_equipment.end()) {
539  free_equipment(item);
540  return *existing;
541  }
542 
543  special_equipment.push_back(item);
544 
545  return item;
546 }
547 
557 static void add_one_item(object *item, struct_map_info *map) {
560  int x, y;
561  sstring name, namepl;
562  uint32_t nrof;
563  object *base;
564 
565  x = item->x;
566  y = item->y;
567  name = item->name;
568  namepl = item->name_pl;
569  nrof = item->nrof;
570 
571  if (item->artifact != NULL) {
572  const artifact *artifact;
573 
574  artifact = find_artifact(item, item->artifact);
575  if (artifact == NULL) {
576  LOG(llevError, "could not find artifact %s [%d] to save data\n", item->artifact, item->type);
577  base = arch_to_object(item->arch);
578  } else {
579  base = arch_to_object(item->arch);
581  }
582  }
583  else {
584  base = arch_to_object(item->arch);
585  }
586 
587  item->x = base->x;
588  item->y = base->y;
589  item->name = base->name;
590  item->name_pl = base->name_pl;
591  item->nrof = base->nrof;
592 
593  if (QUERY_FLAG(item, FLAG_IDENTIFIED) && !QUERY_FLAG(base, FLAG_IDENTIFIED)) {
595  SET_FLAG(base, FLAG_IDENTIFIED);
596  }
597  if (QUERY_FLAG(item, FLAG_UNPAID))
598  SET_FLAG(base, FLAG_UNPAID);
599  get_ob_diff(bf, item, base);
601 
602  add->diff = stringbuffer_finish(bf);
603 
604  item->x = x;
605  item->y = y;
606  item->name = name;
607  item->name_pl = namepl;
608  item->nrof = nrof;
609 
610  if (add->diff == NULL || strcmp(add->diff, "") == 0) {
611  free_equipment(add);
612  return;
613  }
614 
615  add->name = strdup(item->name);
616  add->power = item->item_power;
617  add->calc_power = calc_item_power(item);
618 
619  add = ensure_unique(add);
620  add_map(map, &add->origin);
621 }
622 
631 static void check_equipment(object *item, struct_map_info *map) {
632  if (is_special_equipment(item))
633  add_one_item(item, map);
634 
635  FOR_INV_PREPARE(item, inv)
636  check_equipment(inv, map);
637  FOR_INV_FINISH();
638 }
639 
648 static struct_race *get_race(const char *name) {
649  size_t test;
650  struct_race *item;
651 
652  for (test = 0; test < races.count; test++) {
653  if (strcmp(races.races[test]->name, name) == 0) {
654  races.races[test]->count++;
655  return races.races[test];
656  }
657  }
658 
659  item = (struct_race *)calloc(1, sizeof(struct_race));
660  item->name = strdup(name);
661  item->count = 1;
662  init_map_list(&item->origin);
663 
664  add_race_to_list(item, &races, 0);
665 
666  return item;
667 }
668 
677 static void add_monster(object *monster, struct_map_info *map) {
678  struct_race *race;
679 
680  if (monster->head && monster != monster->head)
681  return;
682 
683  map->min_monster = MIN(monster->level, map->min_monster);
684  map->max_monster = MAX(monster->level, map->max_monster);
685 
686  race = get_race(monster->name ? monster->name : "(null race)");
687  add_map(map, &race->origin);
688  add_race_to_list(race, &map->monsters, 1);
689 }
690 
699 static int sort_race(const void *a, const void *b) {
700  const struct_race *l = *(const struct_race **)a;
701  const struct_race *r = *(const struct_race **)b;
702  return strcasecmp(l->name, r->name);
703 }
704 
712 static int is_road(object *item) {
713  int test;
714  /* Archetypes used as roads. */
715  const char *roads[] = {
716  "cobblestones",
717  "flagstone",
718  "ice_stone",
719  "snow",
720  NULL };
721  const char *partial[] = {
722  "dirtroad_",
723  NULL };
724 
725  for (test = 0; partial[test] != NULL; test++) {
726  if (strstr(item->arch->name, partial[test]) != NULL)
727  return 1;
728  }
729 
730  if (!QUERY_FLAG(item, FLAG_IS_FLOOR))
731  return 0;
732 
733  for (test = 0; roads[test] != NULL; test++) {
734  if (strcmp(item->arch->name, roads[test]) == 0)
735  return 1;
736  }
737 
738  return 0;
739 }
740 
748 static int is_blocking(object *item) {
749  return item->move_block == MOVE_ALL ? 1 : 0;
750 }
751 
762 static int get_elevation_color(int elevation, gdImagePtr elevationmap) {
763  if (elevation > 0)
764  return gdImageColorResolve(elevationmap, 200*elevation/elevation_max, 200-200*elevation/elevation_max, 0);
765  else if (elevation == 0)
766  return gdImageColorResolve(elevationmap, 0, 0, 0);
767  else
768  return gdImageColorResolve(elevationmap, 0, 0, 200-200*elevation/elevation_min);
769 }
770 
779 static void do_exit_map(mapstruct *map) {
780  int tx, ty, x, y;
781  object *test;
782 
783  if (sscanf(map->path, "/world/world_%d_%d", &x, &y) != 2)
784  return;
785 
786  x -= 100;
787  y -= 100;
788 
789  for (tx = 0; tx < MAP_WIDTH(map); tx++) {
790  for (ty = 0; ty < MAP_HEIGHT(map); ty++) {
791  FOR_MAP_PREPARE(map, tx, ty, item) {
792  test = HEAD(item);
793 
794  // Do this before we check for blocked tiles,
795  // otherwise we don't receive elevation data for blocked tiles.
796  int elevation = item->elevation;
797  if (elevation != 0) {
798  elevation_min = MIN(elevation_min, elevation);
799  elevation_max = MAX(elevation_max, elevation);
800  elevation_info[x*50+tx][y*50+ty] = elevation;
801  }
802 
803  if (test->type == EXIT || test->type == TELEPORTER) {
804  if (!test->slaying)
805  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_unlinked_exit);
806  else
807  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_linked_exit);
808  } else if (is_road(test))
809  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_road);
810  else if (is_blocking(test)) {
811  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_blocking);
812  /* can't get on the spot, so no need to go on. */
813  break;
814  } else if (test->move_slow != 0)
815  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_slowing);
816 
817  } FOR_MAP_FINISH();
818  }
819  }
820 }
821 
822 void do_auto_apply(mapstruct *m);
823 
836 static void relative_path(const char *from, const char *to, char *result) {
837  const char *fslash;
838  const char *rslash;
839 
840  result[0] = '\0';
841 
842  fslash = strchr(from+1, '/');
843  if (!fslash) {
844  strcpy(result, to+1);
845  return;
846  }
847 
848  rslash = strchr(to+1, '/');
849  while (fslash && rslash && (fslash-from == rslash-to) && strncmp(from, to, fslash-from+1) == 0) {
850  from = fslash+1;
851  to = rslash+1;
852  fslash = strchr(fslash+1, '/');
853  rslash = strchr(rslash+1, '/');
854  }
855 
856  while (fslash) {
857  strcat(result, "../");
858  fslash = strchr(fslash+1, '/');
859  }
860  if (strlen(result) && result[strlen(result)-1] == '/' && *to == '/')
861  result[strlen(result)-1] = '\0';
862  strcat(result, to);
863 }
864 
875 static int compare_map_info(const struct_map_info *left, const struct_map_info *right) {
876  int c;
877 
878  if (left->tiled_group)
879  left = left->tiled_group;
880  if (right->tiled_group)
881  right = right->tiled_group;
882 
883  // Shortcut -- if both are the same pointer, return 0.
884  // This occurs when tiled maps of the same set are compared to each other.
885  if (left == right)
886  return 0;
887 
888  c = strcasecmp(left->name, right->name);
889  if (c)
890  return c;
891 
892  return strcasecmp(left->path, right->path);
893 }
894 
905 static int sort_map_info(const void *left, const void *right) {
906  const struct_map_info *l = *(const struct_map_info **)left;
907  const struct_map_info *r = *(const struct_map_info **)right;
908  return compare_map_info(l, r);
909 }
910 
921 static int sort_region(const void *left, const void *right) {
922  return strcmp((*((struct_region_info **)left))->reg->name, (*((struct_region_info **)right))->reg->name);
923 }
924 
925 /************************************
926  Start of quest-related definitions.
927 ************************************/
928 
932  char *description;
933  struct struct_quest *quest;
934 };
935 
937 struct struct_quest {
938  char *name;
939  char *description;
940  int number;
943 };
944 
945 static struct_quest **quests = NULL;
947 static int quests_count = 0;
949 static int quests_allocated = 0;
952  list->list = NULL;
953  list->count = 0;
954  list->allocated = 0;
955 }
956 
958  if (list->count == list->allocated) {
959  list->allocated += 10;
960  list->list = (struct_map_in_quest **)realloc(list->list, sizeof(struct_map_in_quest *)*list->allocated);
961  }
962  list->list[list->count++] = item;
963 }
964 
970 static struct_quest *find_quest_info(const char *name) {
971  int test;
972  for (test = 0; test < quests_count; test++) {
973  if (strcmp(quests[test]->name, name) == 0)
974  return quests[test];
975  }
976  return NULL;
977 }
978 
987 static struct_quest *get_quest_info(const char *name) {
989  if (add) {
990  return add;
991  }
992 
994  quests_allocated += 10;
995  quests = (struct_quest **)realloc(quests, sizeof(struct_quest *)*quests_allocated);
996  }
997  add = (struct_quest *)calloc(1, sizeof(struct_quest));
998  add->name = strdup(name);
999  add->number = quests_count;
1001  quests[quests_count] = add;
1002  quests_count++;
1003  return add;
1004 }
1005 
1016 static void add_map_to_quest(struct_map_info *map, const char *name, const char *description) {
1017  struct_map_in_quest *add;
1018  struct_quest *quest = get_quest_info(name);
1019 
1020  add = (struct_map_in_quest *)calloc(1, sizeof(struct_map_in_quest));
1021  add->map = map;
1022  add->quest = quest;
1023  add->description = strdup(description);
1024  while (strlen(add->description) && add->description[strlen(add->description)-1] == '\n')
1025  add->description[strlen(add->description)-1] = '\0';
1026  add_to_struct_map_in_quest_list(&quest->maps, add);
1028 }
1029 
1038 static int sort_struct_map_in_quest(const void *left, const void *right) {
1039  int c;
1040 
1041  const struct_map_in_quest *l = *(const struct_map_in_quest **)left;
1042  const struct_map_in_quest *r = *(const struct_map_in_quest **)right;
1043  const struct_map_info *ml = l->map;
1044  const struct_map_info *mr = r->map;
1045 
1046  if (ml->tiled_group)
1047  ml = ml->tiled_group;
1048  if (mr->tiled_group)
1049  mr = mr->tiled_group;
1050 
1051  c = strcasecmp(ml->name, mr->name);
1052  if (c)
1053  return c;
1054 
1055  return strcasecmp(ml->path, mr->path);
1056 }
1057 
1066 static int sort_struct_quest(const void *left, const void *right) {
1067  const struct_quest *l = *(const struct_quest **)left;
1068  const struct_quest *r = *(const struct_quest **)right;
1069  return strcasecmp(l->name, r->name);
1070 }
1071 
1082 static void define_quest(const char *name, struct_map_info *mainmap, const char *description) {
1083  struct_quest *quest = get_quest_info(name);
1084 
1085  if (quest->description || quest->mainmap) {
1086  printf("warning, multiple quest definition for %s, found in %s and %s.\n", quest->name, quest->mainmap ? quest->mainmap->path : "(unknown map)", mainmap->path);
1087  return;
1088  }
1089  quest->description = strdup(description);
1090  while (strlen(quest->description) && quest->description[strlen(quest->description)-1] == '\n')
1091  quest->description[strlen(quest->description)-1] = '\0';
1092  quest->mainmap = mainmap;
1093 }
1094 
1102  char *start, *end, *next;
1103  char name[500];
1104  char description[500];
1105 
1106  start = strstr(map->lore, "@def");
1107  while (start) {
1108  description[0] = '\0';
1109  /* find name */
1110  end = strstr(start, "\n");
1111  if (end) {
1112  strncpy(name, start+5, end-start-5);
1113  name[end-start-5] = '\0';
1114  next = end+1;
1115  end = strstr(next, "@end");
1116  if (end) {
1117  strncpy(description, next, end-next);
1118  description[end-next] = '\0';
1119  /* need to erase the text. */
1120  memmove(start, end+4, strlen(map->lore)-(end-start+3));
1121  end = start;
1122  }
1123  else {
1124  strcpy(description, next);
1125  *start = '\0';
1126  end = NULL;
1127  }
1128  } else {
1129  strcpy(name, start);
1130  *start = '\0';
1131  end = NULL;
1132  }
1133 
1134  define_quest(name, map, description);
1135  start = end ? strstr(end, "@def") : NULL;
1136  }
1137 
1138  start = strstr(map->lore, "@quest");
1139  while (start) {
1140  description[0] = '\0';
1141  /* find name */
1142  end = strstr(start, "\n");
1143  if (end) {
1144  strncpy(name, start+7, end-start-7);
1145  name[end-start-7] = '\0';
1146  next = end+1;
1147  end = strstr(next, "@end");
1148  if (end) {
1149  strncpy(description, next, end-next);
1150  description[end-next] = '\0';
1151  /* need to erase the text. */
1152  memmove(start, end+4, strlen(map->lore)-(end-start+3));
1153  end = start;
1154  }
1155  else {
1156  strcpy(description, next);
1157  *start = '\0';
1158  end = NULL;
1159  }
1160  } else {
1161  strcpy(name, start);
1162  *start = '\0';
1163  end = NULL;
1164  }
1165 
1167  start = end ? strstr(end, "@quest") : NULL;
1168  }
1169 }
1170 
1171 /************************************
1172  End of quest-related definitions.
1173 ************************************/
1174 
1175 /*********
1176 NPC-related stuff
1177 ********/
1178 
1186 static struct_npc_info *create_npc_info(const object *npc) {
1187  struct_npc_info *info = (struct_npc_info *)calloc(1, sizeof(struct_npc_info));
1188 
1189  info->name = strdup(npc->name ? npc->name : "(null name)");
1190  info->message = strdup(npc->msg ? npc->msg : "(null msg)");
1191  info->x = npc->x;
1192  info->y = npc->y;
1193 
1194  return info;
1195 }
1196 
1204 static void add_npc_to_map(npc_list *list, const object *npc) {
1205  list->push_back(create_npc_info(npc));
1206 }
1207 /* end of NPC stuff */
1208 
1221  size_t map;
1222 
1223  for (map = 0; map < list->count; map++)
1224  if (list->maps[map] == info)
1225  return;
1226 
1227  if (list->count == list->allocated) {
1228  list->allocated += 50;
1229  list->maps = (struct_map_info **)realloc(list->maps, list->allocated*sizeof(struct_map_info *));
1230  }
1231  list->maps[list->count] = info;
1232  list->count++;
1233 }
1234 
1242  struct_map_info *add = (struct_map_info *)calloc(1, sizeof(struct_map_info));
1243 
1244  add->min_monster = 2000;
1245  init_map_list(&add->exits_to);
1246  init_map_list(&add->exits_from);
1247  init_map_list(&add->tiled_maps);
1249  init_race_list(&add->monsters);
1250  add->npcs = new npc_list();
1251  add->readable = new npc_list();
1252  add->tiled_group = NULL;
1253 
1254  return add;
1255 }
1256 
1265 
1266  add_map(add, &tiled_map_list);
1267  return add;
1268 }
1269 
1279 static void merge_tiled_maps(struct_map_info *map, struct_map_info *tiled_map) {
1280  size_t g;
1281  struct_map_info *group = tiled_map->tiled_group;
1282  struct_map_info *change;
1283 
1284  while (group->tiled_maps.count > 0) {
1285  change = group->tiled_maps.maps[group->tiled_maps.count-1];
1286  change->tiled_group = map->tiled_group;
1287  add_map(change, &map->tiled_group->tiled_maps);
1288  group->tiled_maps.count--;
1289  }
1290 
1291  for (g = 0; g < tiled_map_list.count; g++) {
1292  if (tiled_map_list.maps[g] == group) {
1293  if (g < tiled_map_list.count-1)
1296  free(group);
1297  return;
1298  }
1299  }
1300  printf("tiled_map not in tiled_map_list!");
1301  abort();
1302 
1303 }
1304 
1313 static struct_map_info *get_map_info(const char *path) {
1314  struct_map_info *add;
1315  char *tmp;
1316 
1317  for (size_t map = 0; map < maps_list.count; map++) {
1318  if (strcmp(maps_list.maps[map]->path, path) == 0)
1319  return maps_list.maps[map];
1320  }
1321 
1322  add = create_map_info();
1323  add->path = strdup(path);
1324  tmp = strrchr((char *)path, '/');
1325  if (tmp)
1326  add->filename = strdup(tmp+1);
1327  else
1328  add->filename = strdup(path);
1329 
1330  add_map(add, &maps_list);
1331  return add;
1332 }
1333 
1340 static void list_map(const char *path) {
1341  for (auto map = found_maps.begin(); map != found_maps.end(); ++map) {
1342  if (strcmp(path, *map) == 0) {
1343  free(*map);
1344  found_maps.erase(map);
1345  return;
1346  }
1347  }
1348  printf("Map processed but not found in directory reading? %s\n", path);
1349 }
1350 
1361 static void add_map_to_region(struct_map_info *map, region *reg) {
1362  size_t test;
1363  int x, y;
1364 
1365  for (test = 0; test < region_count; test++) {
1366  if (regions[test]->reg == reg)
1367  break;
1368  }
1369  if (test == region_count) {
1370  if (test == region_allocated) {
1371  region_allocated++;
1373  regions[test] = (struct_region_info *)calloc(1, sizeof(struct_region_info));
1374  }
1375  region_count++;
1376  regions[test]->reg = reg;
1377  }
1378  add_map(map, &regions[test]->maps_list);
1379  if (sscanf(map->path, "/world/world_%d_%d", &x, &y) == 2) {
1380  regions[test]->sum_x += (x-100);
1381  regions[test]->sum_y += (y-100);
1382  regions[test]->sum++;
1383  regions[test]->is_world = 1;
1384  }
1385 }
1386 
1395 static void save_picture(FILE *file, gdImagePtr pic) {
1396  if (output_format == OF_PNG)
1397  gdImagePng(pic, file);
1398  else
1399  gdImageJpeg(pic, file, jpeg_quality);
1400 }
1401 
1409 static void add_region_link(mapstruct *source, mapstruct *dest) {
1410  region *s, *d;
1411 
1412  s = get_region_by_map(source);
1413  d = get_region_by_map(dest);
1414  if (s == d)
1415  return;
1416 
1417  region_links[s].insert(d);
1418 }
1419 
1428 static int is_slaying(object *item) {
1429  return (item->type == LOCKED_DOOR || item->type == SPECIAL_KEY || item->type == CONTAINER || item->type == CHECK_INV);
1430 }
1431 
1432 
1441 static struct_slaying_info *get_slaying_struct(const char *slaying) {
1442  for (size_t l = 0; l < slaying_count; l++) {
1443  if (!strcmp(slaying_info[l]->slaying, slaying))
1444  return slaying_info[l];
1445  }
1447  slaying_allocated += 10;
1449  }
1450 
1451  struct_slaying_info *add = (struct_slaying_info *)calloc(1, sizeof(struct_slaying_info));
1452  add->slaying = strdup(slaying);
1453  for (size_t l = 0; l < S_MAX; l++)
1454  init_map_list(&add->maps[l]);
1455 
1456  slaying_info[slaying_count] = add;
1457  slaying_count++;
1458 
1459  return add;
1460 }
1461 
1472 static void add_map_to_slaying(struct_slaying_info *info, int item, struct_map_info *map) {
1473  add_map(map, &info->maps[item]);
1474 }
1475 
1484 static void add_slaying(struct_map_info *map, object *item) {
1485  struct_slaying_info *info;
1486 
1487  if (!item->slaying)
1488  /* can be undefined */
1489  return;
1490 
1491  info = get_slaying_struct(item->slaying);
1492  if (item->type == LOCKED_DOOR)
1493  add_map_to_slaying(info, S_DOOR, map);
1494  else if (item->type == SPECIAL_KEY)
1495  add_map_to_slaying(info, S_KEY, map);
1496  else if (item->type == CONTAINER)
1497  add_map_to_slaying(info, S_CONTAINER, map);
1498  else if (item->type == DETECTOR)
1499  add_map_to_slaying(info, S_DETECTOR, map);
1500  else
1501  add_map_to_slaying(info, S_CONNECT, map);
1502 }
1503 
1512 static void check_slaying_inventory(struct_map_info *map, object *item) {
1513  FOR_INV_PREPARE(item, inv) {
1514  if (is_slaying(inv))
1515  add_slaying(map, inv);
1516  check_slaying_inventory(map, inv);
1517  } FOR_INV_FINISH();
1518 }
1519 
1520 static void generate_picture_path(const char *path, size_t pic_size, char *out, size_t len) {
1521  snprintf(out, len, "%s%s.x%zu%s", root, path, pic_size + 1, output_extensions[output_format]);
1522 }
1523 
1524 static void write_pictures_from_real_size(const char *path, gdImagePtr real, int width, int height) {
1525  char picpath[MAX_BUF];
1526 
1527  generate_picture_path(path, 0, picpath, sizeof(picpath));
1528  make_path_to_file(picpath);
1529  FILE *out = fopen(picpath, "wb+");
1530  save_picture(out, real);
1531  fclose(out);
1532 
1533  for (size_t i = 1; i < num_sizes; i++) {
1534  generate_picture_path(path, i, picpath, sizeof(picpath));
1535  gdImagePtr small = gdImageCreateTrueColor(width*sizes[i], height*sizes[i]);
1536  gdImageCopyResampled(small, real, 0, 0, 0, 0, width*sizes[i], height*sizes[i], width*size_large, height*size_large);
1537  out = fopen(picpath, "wb+");
1538  save_picture(out, small);
1539  fclose(out);
1540  gdImageDestroy(small);
1541  }
1542 }
1543 
1552 static void process_map(struct_map_info *info) {
1553  mapstruct *m;
1554  int x, y, isworld;
1555  gdImagePtr pic = nullptr;
1556  struct stat stats;
1557  struct stat statspic;
1558  char exit_path[500];
1559  char tmppath[MAX_BUF];
1560  char picpath[num_sizes][MAX_BUF];
1561  int needpic = 0;
1562  struct_map_info *link;
1563 
1564  if (list_unused_maps)
1565  list_map(info->path);
1566 
1567  if (show_maps)
1568  printf(" processing map %s\n", info->path);
1569 
1570  m = ready_map_name(info->path, 0);
1571  if (!m) {
1572  printf("couldn't load map %s\n", info->path);
1573  return;
1574  }
1575 
1576  do_exit_map(m);
1577 
1578  if (!rawmaps)
1579  do_auto_apply(m);
1580 
1581  info->level = m->difficulty;
1582  if (m->maplore) {
1583  info->lore = strdup(m->maplore);
1584  process_map_lore(info);
1585  }
1586  if (m->reset_group) {
1587  info->reset_group = add_string(m->reset_group);
1588  reset_groups.insert(m->reset_group);
1589  }
1590 
1591  isworld = (sscanf(info->path, "/world/world_%d_%d", &x, &y) == 2);
1592 
1593  if (m->name)
1594  info->name = strdup(m->name);
1595  else
1596  info->name = strdup(info->filename);
1597 
1598  info->cfregion = get_region_by_map(m);
1599  add_map_to_region(info, info->cfregion);
1600 
1601  for (int i = 0; i < num_sizes; i++) {
1602  generate_picture_path(info->path, i, picpath[i], sizeof(picpath[i]));
1603  }
1604 
1605  if (force_pics)
1606  needpic = 1;
1607  else if (generate_pics) {
1608  create_pathname(info->path, tmppath, MAX_BUF);
1609  stat(tmppath, &stats);
1610  if (stat(picpath[0], &statspic) || (statspic.st_mtime < stats.st_mtime))
1611  needpic = 1;
1612  }
1613  else
1614  needpic = 0;
1615 
1616  if (needpic) {
1617  pic = gdImageCreateTrueColor(MAP_WIDTH(m)*size_large, MAP_HEIGHT(m)*size_large);
1618  created_pics++;
1619  }
1620  else
1621  cached_pics++;
1622 
1623  for (x = 0; x < 4; x++)
1624  if (m->tile_path[x] != NULL) {
1625  path_combine_and_normalize(m->path, m->tile_path[x], exit_path, sizeof(exit_path));
1626  create_pathname(exit_path, tmppath, MAX_BUF);
1627  if (stat(tmppath, &stats)) {
1628  printf(" map %s doesn't exist in map %s, for tile %d.\n", exit_path, info->path, x);
1629  }
1630 
1631  if (isworld) {
1632  link = get_map_info(exit_path);
1633  add_map(link, &info->exits_from);
1634  add_map(info, &link->exits_to);
1635 
1636  if (do_regions_link) {
1637  mapstruct *link = ready_map_name(exit_path, 0);
1638 
1639  if (link && link != m) {
1640  /* no need to link a map with itself. Also, if the exit points to the same map, we don't
1641  * want to reset it. */
1642  add_region_link(m, link);
1643  link->reset_time = 1;
1644  link->in_memory = MAP_IN_MEMORY;
1645  delete_map(link);
1646  }
1647  }
1648  } else {
1649  link = get_map_info(exit_path);
1650  info->tiles[x] = link;
1651  if (link->tiled_group) {
1652  if (info->tiled_group && link->tiled_group != info->tiled_group) {
1653  merge_tiled_maps(info, link);
1654  continue;
1655  }
1656  if (link->tiled_group == info->tiled_group) {
1657  continue;
1658  }
1659  if (!info->tiled_group) {
1660  add_map(info, &link->tiled_group->tiled_maps);
1661  continue;
1662  }
1663  }
1664 
1665  if (!info->tiled_group) {
1666  info->tiled_group = create_tiled_map();
1667  add_map(info, &info->tiled_group->tiled_maps);
1668  }
1669  link->tiled_group = info->tiled_group;
1670  add_map(link, &info->tiled_group->tiled_maps);
1671  }
1672  }
1673 
1674  info->width = MAP_WIDTH(m);
1675  info->height = MAP_HEIGHT(m);
1676 
1677  for (x = MAP_WIDTH(m)-1; x >= 0; x--)
1678  for (y = MAP_HEIGHT(m)-1; y >= 0; y--) {
1679  FOR_MAP_PREPARE(m, x, y, item) {
1680  if (item->type == EXIT || item->type == TELEPORTER || item->type == PLAYER_CHANGER) {
1681  char ep[500];
1682  const char *start;
1683 
1684  if (!item->slaying) {
1685  ep[0] = '\0';
1686  if (warn_no_path)
1687  printf(" exit without any path at %d, %d on %s\n", item->x, item->y, info->path);
1688  } else {
1689  memset(ep, 0, 500);
1690  if (strcmp(item->slaying, "/!"))
1691  strcpy(ep, EXIT_PATH(item));
1692  else {
1693  if (!item->msg) {
1694  printf(" random map without message in %s at %d, %d\n", info->path, item->x, item->y);
1695  } else {
1696  /* Some maps have a 'exit_on_final_map' flag, ignore it. */
1697  start = strstr(item->msg, "\nfinal_map ");
1698  if (!start && strncmp(item->msg, "final_map", strlen("final_map")) == 0)
1699  /* Message start is final_map, nice */
1700  start = item->msg;
1701  if (start) {
1702  char *end = strchr((char *)start+1, '\n');
1703 
1704  start += strlen("final_map")+2;
1705  strncpy(ep, start, end-start);
1706  }
1707  }
1708  }
1709 
1710  if (strlen(ep)) {
1711  path_combine_and_normalize(m->path, ep, exit_path, 500);
1712  create_pathname(exit_path, tmppath, MAX_BUF);
1713  if (stat(tmppath, &stats)) {
1714  printf(" map %s doesn't exist in map %s, at %d, %d.\n", ep, info->path, item->x, item->y);
1715  } else {
1716  link = get_map_info(exit_path);
1717  add_map(link, &info->exits_from);
1718  add_map(info, &link->exits_to);
1719 
1720  if (do_regions_link) {
1721  mapstruct *link = ready_map_name(exit_path, 0);
1722 
1723  if (link && link != m) {
1724  /* no need to link a map with itself. Also, if the exit points to the same map, we don't
1725  * want to reset it. */
1726  add_region_link(m, link);
1727  link->reset_time = 1;
1728  link->in_memory = MAP_IN_MEMORY;
1729  delete_map(link);
1730  }
1731  }
1732  }
1733  }
1734  }
1735  } else if (is_slaying(item))
1736  add_slaying(info, item);
1737 
1738  check_equipment(item, info);
1739 
1740  check_slaying_inventory(info, item);
1741 
1742  if (QUERY_FLAG(item, FLAG_MONSTER)) {
1743  /* need to get the "real" archetype, as the item's archetype can certainly be a temporary one. */
1744  archetype *arch = find_archetype(item->arch->name);
1745 
1746  add_monster(item, info);
1747  if (arch != NULL && (QUERY_FLAG(item, FLAG_UNAGGRESSIVE) || QUERY_FLAG(item, FLAG_FRIENDLY)) && (item->msg != arch->clone.msg) && (item->msg != NULL))
1748  add_npc_to_map(info->npcs, item);
1749  } else if ((item->type == SIGN || item->type == BOOK) && (item->msg != item->arch->clone.msg) && (item->msg != NULL)) {
1750  add_npc_to_map(info->readable, item);
1751  }
1752 
1753  if (item->invisible)
1754  continue;
1755 
1756  if (needpic) {
1757  int sx, sy, hx, hy;
1758 
1759  if (gdfaces.size() <= item->face->number)
1760  gdfaces.resize(item->face->number + 1, nullptr);
1761 
1762  if (gdfaces[item->face->number] == NULL) {
1763  face_sets *fs = find_faceset(get_face_fallback(tileset, item->face->number));
1764 
1765  gdfaces[item->face->number] = gdImageCreateFromPngPtr(fs->faces[item->face->number].datalen, fs->faces[item->face->number].data);
1766  pics_allocated++;
1767  }
1768  if (item->head || item->more) {
1769  object_get_multi_size(item, &sx, &sy, &hx, &hy);
1770  } else {
1771  hx = 0;
1772  hy = 0;
1773  }
1774  if (gdfaces[item->face->number] != NULL && ((!item->head && !item->more) || (item->arch->clone.x+hx == 0 && item->arch->clone.y+hy == 0))) {
1775  gdImageCopy(pic, gdfaces[item->face->number], x*size_large, y*size_large, 0, 0, gdfaces[item->face->number]->sx, gdfaces[item->face->number]->sy);
1776  }
1777  }
1778  } FOR_MAP_FINISH();
1779  }
1780 
1781  if (needpic) {
1783  gdImageDestroy(pic);
1784  info->pic_was_done = 1;
1785  }
1786 
1787  m->reset_time = 1;
1788  m->in_memory = MAP_IN_MEMORY;
1789  delete_map(m);
1790 }
1791 
1795 static void write_world_map(void) {
1796 #define SIZE 50
1797  int x, y;
1798  FILE *out;
1799  int wx, wy;
1800  char file[500];
1801  char mapleft[10], maptop[10], mapright[10], mapbottom[10], mappath[5000];
1802  char name[100];
1803  gdImagePtr pic;
1804  gdImagePtr small;
1805  gdFontPtr font;
1806  int color;
1807 
1808  if (!world_map)
1809  return;
1810 
1811  printf("Generating world map in world.html...");
1812  fflush(stdout);
1813 
1814  pic = gdImageCreateTrueColor(SIZE*30, SIZE*30);
1815 
1816  strcpy(file, root);
1817  strcat(file, "/world.html");
1818 
1819  wx = 100;
1820  wy = 100;
1821 
1822  for (y = 0; y < 30; y++) {
1823  for (x = 0; x < 30; x++) {
1824  snprintf(name, sizeof(name), "world_%d_%d", wx, wy);
1825  snprintf(mapleft, sizeof(mapleft), "%d", SIZE*x);
1826  snprintf(maptop, sizeof(maptop), "%d", SIZE*y);
1827  snprintf(mapright, sizeof(mapright), "%d", SIZE*(x+1)-1);
1828  snprintf(mapbottom, sizeof(mapbottom), "%d", SIZE*(y+1)-1);
1829 
1830  snprintf(mappath, sizeof(mappath), "%s/world/%s.x1%s", root, name, output_extensions[output_format]);
1831 
1832  out = fopen(mappath, "rb");
1833  if (!out) {
1834  printf("\n warning: large pic not found for world_%d_%d", wx, wy);
1835  wx++;
1836  continue;
1837  }
1838  if (output_format == OF_PNG)
1839  small = gdImageCreateFromPng(out);
1840  else
1841  small = gdImageCreateFromJpeg(out);
1842  fclose(out);
1843  if (!small) {
1844  printf("\n warning: pic not found for world_%d_%d", wx, wy);
1845  wx++;
1846  continue;
1847  }
1848  gdImageCopyResized(pic, small, SIZE*x, SIZE*y, 0, 0, SIZE, SIZE, small->sx, small->sy);
1849  gdImageDestroy(small);
1850 
1851  wx++;
1852  }
1853  wy++;
1854  wx = 100;
1855  }
1856 
1857  snprintf(mappath, sizeof(mappath), "%s/world_raw%s", root, output_extensions[output_format]);
1858  out = fopen(mappath, "wb+");
1859  save_picture(out, pic);
1860  fclose(out);
1861 
1862  /* Write region names. */
1863  small = gdImageCreateTrueColor(SIZE*30, SIZE*30);
1864  font = gdFontGetGiant();
1865  color = gdImageColorAllocateAlpha(pic, 255, 0, 0, 20);
1866  for (size_t region = 0; region < region_allocated; region++) {
1867  if (!regions[region]->is_world || regions[region]->sum == 0)
1868  continue;
1869 
1870  x = regions[region]->sum_x*SIZE/regions[region]->sum+SIZE/2-strlen(regions[region]->reg->name)*font->w/2;
1871  y = regions[region]->sum_y*SIZE/regions[region]->sum+SIZE/2-font->h/2;
1872  gdImageString(small, font, x, y, (unsigned char *)regions[region]->reg->name, color);
1873  gdImageString(pic, font, x, y, (unsigned char *)regions[region]->reg->name, color);
1874 
1875  /* For exit/road map, size isn't the same. */
1876  x = regions[region]->sum_x*50/regions[region]->sum+50/2-strlen(regions[region]->reg->name)*font->w/2;
1877  y = regions[region]->sum_y*50/regions[region]->sum+50/2-font->h/2;
1878  gdImageString(infomap, font, x, y, (unsigned char *)regions[region]->reg->name, color);
1879  }
1880 
1881  snprintf(mappath, sizeof(mappath), "%s/world_regions%s", root, output_extensions[output_format]);
1882  out = fopen(mappath, "wb+");
1883  save_picture(out, small);
1884  fclose(out);
1885  gdImageDestroy(small);
1886 
1887  snprintf(mappath, sizeof(mappath), "%s/world%s", root, output_extensions[output_format]);
1888  out = fopen(mappath, "wb+");
1889  save_picture(out, pic);
1890  fclose(out);
1891  gdImageDestroy(pic);
1892 
1893  printf(" done.\n");
1894 #undef SIZE
1895 }
1896 
1898 static void fix_map_names(void) {
1899  for (size_t map = 0; map < maps_list.count; map++) {
1900  if (maps_list.maps[map]->name)
1901  continue;
1902  if (!maps_list.maps[map]->filename) {
1903  printf("map without path!\n");
1904  abort();
1905  }
1906  maps_list.maps[map]->name = strdup(maps_list.maps[map]->filename);
1907  }
1908 }
1909 
1916 static void fix_tiled_map(void) {
1917  size_t map, tile;
1918  char name[500];
1919  char *slash, *test;
1920  region *cfregion;
1921 
1922  for (map = 0; map < tiled_map_list.count; map++) {
1923  if (tiled_map_list.maps[map]->tiled_maps.count == 0) {
1924  printf("empty tiled map group!");
1925  abort();
1926  }
1927 
1928  snprintf(name, sizeof(name), "tiled_map_group_%zu", map);
1929  tiled_map_list.maps[map]->filename = strdup(name);
1930 
1931  cfregion = NULL;
1932  test = NULL;
1933 
1934  for (tile = 0; tile < tiled_map_list.maps[map]->tiled_maps.count; tile++) {
1935  if (tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion == NULL)
1936  /* map not processed, ignore it. */
1937  continue;
1938 
1939  if (!cfregion)
1940  cfregion = tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion;
1941  else if (cfregion != tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion) {
1942  printf("*** warning: tiled maps %s and %s not in same region (%s and %s).\n",
1945  cfregion = NULL;
1946  }
1947 
1948  if (strcmp(tiled_map_list.maps[map]->tiled_maps.maps[tile]->name, tiled_map_list.maps[map]->tiled_maps.maps[tile]->filename)) {
1949  /* map has a custom name, use it */
1950  if (!test)
1951  test = tiled_map_list.maps[map]->tiled_maps.maps[tile]->name;
1952  }
1953  }
1954 
1955  if (!test) {
1956  /* this can happen of course if only partial maps were processed, but well... */
1957  printf("*** warning: tiled map without any name. First map path %s\n", tiled_map_list.maps[map]->tiled_maps.maps[0]->path);
1958  test = name;
1959  }
1960 
1961  tiled_map_list.maps[map]->name = strdup(test);
1962  tiled_map_list.maps[map]->cfregion = cfregion;
1963 
1964  strncpy(name, tiled_map_list.maps[map]->tiled_maps.maps[0]->path, sizeof(name));
1965  slash = strrchr(name, '/');
1966  if (!slash)
1967  snprintf(name, sizeof(name), "/");
1968  else
1969  *(slash+1) = '\0';
1970  strncat(name, tiled_map_list.maps[map]->filename, sizeof(name) - strlen(name) - 1);
1971  tiled_map_list.maps[map]->path = strdup(name);
1972  }
1973 }
1974 
1985 static void fix_exits_for_map(struct_map_info *current, struct_map_list *from, int is_from) {
1986  int map, max;
1987  struct_map_info *group;
1988 
1989  max = from->count-1;
1990  for (map = max; map >= 0; map--) {
1991  if (from->maps[map]->tiled_group) {
1992  group = from->maps[map]->tiled_group;
1993  if (map != max)
1994  from->maps[map] = from->maps[max];
1995  from->count--;
1996  max--;
1997  add_map(group, from);
1998  add_map(current->tiled_group ? current->tiled_group : current, is_from ? &group->exits_to : &group->exits_from);
1999  }
2000  }
2001 }
2002 
2004 static void fix_exits_to_tiled_maps(void) {
2005  int map, max;
2006  struct_map_info *group;
2007 
2008  for (map = 0; static_cast<size_t>(map) < maps_list.count; map++) {
2011  }
2012 
2013  for (size_t region = 0; region < region_count; region++) {
2014  max = regions[region]->maps_list.count-1;
2015  for (map = max; map >= 0; map--) {
2016  if (regions[region]->maps_list.maps[map]->tiled_group) {
2017  group = regions[region]->maps_list.maps[map]->tiled_group;
2018  if (map != max)
2021  max--;
2022  add_map(group, &regions[region]->maps_list);
2023  }
2024  }
2025  }
2026 }
2027 
2032 static void fix_tiled_map_monsters(void) {
2033  int map, max;
2034  struct_map_info *group;
2035 
2036  for (size_t race = 0; race < races.count; race++) {
2037  max = races.races[race]->origin.count-1;
2038  for (map = max; map >= 0; map--) {
2039  if (races.races[race]->origin.maps[map]->tiled_group) {
2040  group = races.races[race]->origin.maps[map]->tiled_group;
2041  if (map != max)
2042  races.races[race]->origin.maps[map] = races.races[race]->origin.maps[max];
2043  races.races[race]->origin.count--;
2044  max--;
2045  add_map(group, &races.races[race]->origin);
2046  }
2047  }
2048  }
2049 
2050  for (map = 0; static_cast<size_t>(map) < maps_list.count; map++) {
2051  if (maps_list.maps[map]->tiled_group) {
2052  for (size_t race = 0; race < maps_list.maps[map]->monsters.count; race++) {
2054  }
2055  }
2056  }
2057 }
2058 
2060  size_t test;
2061  char picpath[500];
2062  struct stat stats;
2063 
2064  for (size_t size = 0; size < num_sizes; size++) {
2065  generate_picture_path(map->path, size, picpath, sizeof(picpath));
2066  if (stat(picpath, &stats))
2067  return 1;
2068  }
2069 
2070  for (test = 0; test < map->tiled_maps.count; test++) {
2071  if (map->tiled_maps.maps[test]->pic_was_done)
2072  return 1;
2073  }
2074 
2075  return 0;
2076 }
2077 
2090  int xmin = 0, xmax = 0, ymin = 0, ymax = 0, count, last;
2091  size_t tiled;
2092  char picpath[500];
2093  gdImagePtr large, load;
2094  FILE *out;
2095  struct_map_info *current;
2096 
2097  if (!generate_pics)
2098  return;
2099 
2100  printf(" Generating composite map for %s...", map->name);
2101  fflush(stdout);
2102 
2103  if (!tiled_map_need_pic(map)) {
2104  printf(" already uptodate.\n");
2105  return;
2106  }
2107 
2108  count = map->tiled_maps.count;
2109  if (count == 0) {
2110  printf("Tiled map without tiled maps?\n");
2111  abort();
2112  }
2113  map->tiled_maps.maps[0]->processed = 1;
2114  map->tiled_maps.maps[0]->tiled_x_from = 0;
2115  map->tiled_maps.maps[0]->tiled_y_from = 0;
2116 
2117  while (count > 0) {
2118  last = count;
2119 
2120  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2121  current = map->tiled_maps.maps[tiled];
2122  if (current->processed != 1)
2123  continue;
2124 
2125  count--;
2126 
2127  if ((current->tiles[0]) && (current->tiles[0]->processed == 0)) {
2128  current->tiles[0]->processed = 1;
2129  current->tiles[0]->tiled_x_from = current->tiled_x_from;
2130  current->tiles[0]->tiled_y_from = current->tiled_y_from-current->tiles[0]->height;
2131  }
2132  if ((current->tiles[1]) && (current->tiles[1]->processed == 0)) {
2133  current->tiles[1]->processed = 1;
2134  current->tiles[1]->tiled_x_from = current->tiled_x_from+current->width;
2135  current->tiles[1]->tiled_y_from = current->tiled_y_from;
2136  }
2137  if ((current->tiles[2]) && (current->tiles[2]->processed == 0)) {
2138  current->tiles[2]->processed = 1;
2139  current->tiles[2]->tiled_x_from = current->tiled_x_from;
2140  current->tiles[2]->tiled_y_from = current->tiled_y_from+current->height;
2141  }
2142  if ((current->tiles[3]) && (current->tiles[3]->processed == 0)) {
2143  current->tiles[3]->processed = 1;
2144  current->tiles[3]->tiled_x_from = current->tiled_x_from-current->tiles[3]->width;
2145  current->tiles[3]->tiled_y_from = current->tiled_y_from;
2146  }
2147  }
2148 
2149  if (last == count) {
2150  printf("do_tiled_map_picture: didn't process any map in %s (%d left)??\n", map->path, last);
2151  abort();
2152  }
2153  }
2154 
2155  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2156  if (map->tiled_maps.maps[tiled]->tiled_x_from < xmin)
2157  xmin = map->tiled_maps.maps[tiled]->tiled_x_from;
2158  if (map->tiled_maps.maps[tiled]->tiled_y_from < ymin)
2159  ymin = map->tiled_maps.maps[tiled]->tiled_y_from;
2160  if (map->tiled_maps.maps[tiled]->tiled_x_from+map->tiled_maps.maps[tiled]->width > xmax)
2161  xmax = map->tiled_maps.maps[tiled]->tiled_x_from+map->tiled_maps.maps[tiled]->width;
2162  if (map->tiled_maps.maps[tiled]->tiled_y_from+map->tiled_maps.maps[tiled]->height > ymax)
2163  ymax = map->tiled_maps.maps[tiled]->tiled_y_from+map->tiled_maps.maps[tiled]->height;
2164  }
2165 
2166  large = gdImageCreateTrueColor(size_large*(xmax-xmin), size_large*(ymax-ymin));
2167 
2168  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2169  generate_picture_path(map->tiled_maps.maps[tiled]->path, 0, picpath, sizeof(picpath));
2170 
2171  out = fopen(picpath, "rb");
2172  if (!out) {
2173  printf("\n do_tiled_map_picture: warning: pic file %s not found for %s (errno=%d)\n", picpath, map->tiled_maps.maps[tiled]->path, errno);
2174  continue;
2175  }
2176  if (output_format == OF_PNG)
2177  load = gdImageCreateFromPng(out);
2178  else
2179  load = gdImageCreateFromJpeg(out);
2180  fclose(out);
2181  if (!load) {
2182  printf("\n do_tiled_map_picture: warning: pic not found for %s\n", map->tiled_maps.maps[tiled]->path);
2183  continue;
2184  }
2185  gdImageCopy(large, load, size_large*(map->tiled_maps.maps[tiled]->tiled_x_from-xmin), size_large*(map->tiled_maps.maps[tiled]->tiled_y_from-ymin), 0, 0, load->sx, load->sy);
2186  gdImageDestroy(load);
2187  }
2188 
2189  write_pictures_from_real_size(map->path, large, xmax-xmin, ymax-ymin);
2190 
2191  gdImageDestroy(large);
2192 
2193  printf(" done.\n");
2194 }
2195 
2198 
2199  do_tiled_map_picture(map);
2200 
2203 // write_map_page(map);
2204 }
2205 
2207 static void write_tiled_maps(void) {
2208  printf("Writing tiled map information...\n");
2209 
2210  for (size_t map = 0; map < tiled_map_list.count; map++)
2212 
2213  printf(" done.\n");
2214 }
2215 
2216 static std::vector<quest_definition *> system_quests;
2217 
2218 static void quest_callback(const quest_definition *quest, void *) {
2219  if (list_system_quests || !quest->quest_is_system) {
2220  system_quests.push_back(const_cast<quest_definition *>(quest));
2221  }
2222 }
2223 
2224 static std::shared_ptr<inja::Environment> env;
2225 static nlohmann::json all_data;
2226 static std::set<std::string> rendered_templates;
2227 static std::map<struct_map_info *, std::string> reverse_maps;
2228 static std::map<region *, std::string> reverse_regions;
2235 static struct_map_info *find_map_by_key(const std::string &key) {
2236  auto found = std::find_if(reverse_maps.cbegin(), reverse_maps.cend(), [&key] (auto c) { return c.second == key; });
2237  if (found != reverse_maps.cend())
2238  return found->first;
2239  return nullptr;
2240 }
2241 
2247 static region *find_region_by_key(const std::string &key) {
2248  auto found = std::find_if(reverse_regions.cbegin(), reverse_regions.cend(), [&key] (auto c) { return c.second == key; });
2249  if (found != reverse_regions.cend())
2250  return found->first;
2251  return nullptr;
2252 }
2253 
2259 static nlohmann::json create_maps_array(struct_map_list &maps) {
2260  nlohmann::json result = nlohmann::json::array();
2261  for (size_t m = 0; m < maps.count; m++) {
2262  auto map = reverse_maps.find(maps.maps[m]);
2263  if (map != reverse_maps.end()) {
2264  result.push_back(map->second);
2265  }
2266  }
2267  return result;
2268 }
2269 
2275 static nlohmann::json create_npc_array(npc_list &list) {
2276  nlohmann::json result;
2277  for (size_t n = 0; n < list.size(); n++) {
2278  auto npc = list[n];
2279  result.push_back({
2280  { "name", npc->name },
2281  { "x", npc->x },
2282  { "y", npc->y },
2283  { "message", npc->message },
2284  });
2285  }
2286  return result;
2287 }
2288 
2294 static nlohmann::json create_race_array(struct_race_list &list) {
2295  nlohmann::json result;
2296  for (size_t n = 0; n < list.count; n++) {
2297  auto race = list.races[n];
2298  result.push_back({
2299  { "name", race->name },
2300  { "count", race->count },
2301  });
2302  }
2303  return result;
2304 }
2305 
2312  nlohmann::json ret = nlohmann::json::array();
2313  for (size_t m = 0; m < list.count; m++) {
2314  auto q = list.list[m];
2315  if (!q->map || !q->description)
2316  continue;
2317  ret.push_back({
2318  { "map", reverse_maps.find(q->map)->second },
2319  { "description", q->description },
2320  { "quest", q->quest->name },
2321  { "number", q->quest->number },
2322  });
2323  }
2324 
2325  return ret;
2326 }
2327 
2328 static const char *remove_trailing_slash(const char *path)
2329 {
2330  return path && path[0] == '/' ? path + 1 : path;
2331 }
2332 
2339 static nlohmann::json create_map_object(struct_map_info *map, const std::string &key) {
2340  return {
2341  { "_key", key },
2342  { "name", map->name },
2343  { "path", remove_trailing_slash(map->path) },
2344  { "region", map->cfregion ? reverse_regions[map->cfregion] : "reg_ffff" },
2345  { "level", map->level },
2346  { "reset_group", map->reset_group ? map->reset_group : "" },
2347  { "lore", map->lore && map->lore[0] ? map->lore : "" },
2348  { "exits_to", create_maps_array(map->exits_to) },
2349  { "exits_from", create_maps_array(map->exits_from) },
2350  { "npcs", create_npc_array(*map->npcs) },
2351  { "readables", create_npc_array(*map->readable) },
2352  { "monsters", create_race_array(map->monsters) },
2353  { "quests", create_map_in_quest_array(map->quests) },
2354  };
2355 }
2356 
2363 static nlohmann::json create_quest_object(struct_quest *quest, const std::string &key) {
2364  return {
2365  { "_key", key },
2366  { "number", quest->number },
2367  { "name", quest->name ? quest->name : "" },
2368  { "description", quest->description ? quest->description : "" },
2369  { "main_map", quest->mainmap ? reverse_maps.find(quest->mainmap)->second : "" },
2370  { "maps", create_map_in_quest_array(quest->maps) },
2371  };
2372 }
2373 
2379  char buf[50];
2380  for (size_t map = 0; map < list.count; map++) {
2381  auto cur = list.maps[map];
2382  if (cur->tiled_group)
2383  continue;
2384  snprintf(buf, sizeof(buf), "map_%04lu", map);
2385  reverse_maps.insert(std::make_pair(cur, buf));
2386  qsort(cur->exits_to.maps, cur->exits_to.count, sizeof(struct_map_info *), sort_map_info);
2387  qsort(cur->exits_from.maps, cur->exits_from.count, sizeof(struct_map_info *), sort_map_info);
2388  qsort(cur->monsters.races, cur->monsters.count, sizeof(struct_race *), sort_race);
2389  }
2390 }
2391 
2398  for (size_t map = 0; map < src.count; map++)
2399  add_map(src.maps[map], &dest);
2400 }
2401 
2407 static nlohmann::json create_region_array(const std::set<region *> &regions) {
2408  nlohmann::json ret = nlohmann::json::array();
2409  for (auto reg : regions) {
2410  auto r = reverse_regions.find(reg);
2411  if (r != reverse_regions.end()) {
2412  ret.push_back((*r).second);
2413  }
2414  }
2415  return ret;
2416 }
2417 
2418 static inja::TemplateStorage templateCache;
2419 static inja::Template get_template(const std::string &filename) {
2420  auto find = templateCache.find(filename);
2421  if (find != templateCache.end()) {
2422  return find->second;
2423  }
2424  inja::Template parsed = env->parse_template(filename);
2425  templateCache[filename] = parsed;
2426  return parsed;
2427 }
2428 
2433 static void fill_json(nlohmann::json &json) {
2434  nlohmann::json maps;
2435  char buf[10];
2436  struct_map_list all_maps;
2437  bool need_unknown_region = false;
2438  nlohmann::json search;
2439 
2440  init_map_list(&all_maps);
2441  append_map_list(all_maps, maps_list);
2442  append_map_list(all_maps, tiled_map_list);
2443  qsort(all_maps.maps, all_maps.count, sizeof(struct_map_info *), sort_map_info);
2444 
2445  fill_reverse_maps(all_maps);
2446 
2447  for (size_t reg = 0; reg < region_count; reg++) {
2448  auto region = regions[reg];
2449  snprintf(buf, sizeof(buf), "reg_%04lu", reg);
2450  reverse_regions.insert(std::make_pair(region->reg, buf));
2451  }
2452 
2453  for (size_t reg = 0; reg < region_count; reg++) {
2454  auto region = regions[reg];
2455  qsort(region->maps_list.maps, region->maps_list.count, sizeof(struct_map_info *), sort_map_info);
2456  nlohmann::json r = {
2457  { "_key", reverse_regions[region->reg] },
2458  { "_index", reg },
2459  { "name", region->reg->name },
2460  { "longname", region->reg->longname },
2461  { "description", region->reg->msg ? region->reg->msg : "" },
2462  { "maps", create_maps_array(region->maps_list) },
2463  { "links", create_region_array(region_links[region->reg]) },
2464  };
2465  json["regions"].push_back(r);
2466  auto link = env->render(get_template("search-links/region"), r);
2467  search["reg_" + std::to_string(reg)] = {
2468  { "type" , SearchType::Region },
2469  { "name", region->reg->longname },
2470  { "text", std::string(region->reg->msg ? region->reg->msg : "") },
2471  { "url", link },
2472  };
2473  }
2474 
2475  size_t map_index = 0;
2476  for (auto map : reverse_maps) {
2477  auto cur = map.first;
2478  if (cur->tiled_group)
2479  continue;
2480  if (cur->cfregion == nullptr)
2481  need_unknown_region = true;
2482  auto m = create_map_object(cur, map.second);
2483  m["_index"] = map_index;
2484  json["maps"].push_back(m);
2485  auto link = env->render(get_template("search-links/map"), m);
2486  search["map_" + std::to_string(map_index++)] = {
2487  { "type", SearchType::Map },
2488  { "name", cur->name },
2489  { "text", std::string(cur->lore ? cur->lore : "") },
2490  { "url", link },
2491  };
2492  }
2493 
2494  if (need_unknown_region) {
2495  json["regions"].push_back({
2496  { "_key", "reg_ffff" },
2497  { "name", "unknown" },
2498  { "longname", "unknown" },
2499  { "description", "unknown" },
2500  { "maps", nlohmann::json::array() },
2501  { "links", nlohmann::json::array() },
2502  });
2503  }
2504 
2505  json["reset_groups"] = nlohmann::json::array();
2506  for (const auto &rg : reset_groups) {
2507  json["reset_groups"].push_back(rg);
2508  }
2509 
2510  json["items"] = nlohmann::json::array();
2511  for (size_t idx = 0; idx < special_equipment.size(); idx++) {
2512  auto eq = special_equipment[idx];
2513  nlohmann::json item = {
2514  { "_index", idx },
2515  { "name", eq->name },
2516  { "power", eq->power },
2517  { "calc_power", eq->calc_power },
2518  { "diff", eq->diff },
2519  { "maps", create_maps_array(eq->origin) },
2520  };
2521  json["items"][idx] = item;
2522  auto link = env->render(get_template("search-links/item"), item);
2523  search["item_" + std::to_string(idx)] = {
2524  { "type", SearchType::Item },
2525  { "name", eq->name },
2526  { "url", link },
2527  };
2528  }
2529 
2530  json["monsters"] = nlohmann::json::array();
2531  for (size_t item = 0; item < races.count; item++) {
2532  auto race = races.races[item];
2533  qsort(race->origin.maps, race->origin.count, sizeof(struct_map_info *), sort_map_info);
2534  nlohmann::json m = {
2535  { "_index", item },
2536  { "name", race->name },
2537  { "count", race->count },
2538  { "maps", create_maps_array(race->origin) },
2539  };
2540  json["monsters"].push_back(m);
2541  auto link = env->render(get_template("search-links/monster"), m);
2542  search["monster_" + std::to_string(item)] = {
2543  { "type", SearchType::Monster },
2544  { "name", race->name },
2545  { "url", link },
2546  };
2547  }
2548 
2549  json["system_quests"] = nlohmann::json::array();
2550  for (size_t q = 0; q < system_quests.size(); q++) {
2551  auto quest = system_quests[q];
2552  nlohmann::json j({
2553  { "_index", q },
2554  { "code", quest->quest_code },
2555  { "title", quest->quest_title },
2556  { "description", quest->quest_description ? quest->quest_description : "" },
2557  { "replayable", quest->quest_restart },
2558  { "steps", nlohmann::json::array() },
2559  { "maps", nlohmann::json::array() },
2560  });
2561 
2562  if (detail_quests) {
2563  std::sort(quest->steps.begin(), quest->steps.end(), [] (auto left, auto right) { return left->step < right->step; });
2564  for (size_t s = 0; s < quest->steps.size(); s++) {
2565  j["steps"].push_back({
2566  { "description", quest->steps[s]->step_description ? quest->steps[s]->step_description : "" },
2567  { "is_completion", quest->steps[s]->is_completion_step ? true : false },
2568  });
2569  }
2570 
2571  auto qim = find_quest_info(quest->quest_code);
2572  if (qim) {
2573  for (size_t m = 0; m < qim->maps.count; m++) {
2574  auto map = reverse_maps.find(qim->maps.list[m]->map);
2575  assert(map != reverse_maps.end());
2576  j["maps"].push_back({
2577  { "description", qim->maps.list[m]->description },
2578  { "map", map->second },
2579  });
2580  }
2581  }
2582  }
2583  json["system_quests"].push_back(j);
2584  search["quest_" + std::to_string(q)] = {
2585  { "type", SearchType::Quest },
2586  { "name", quest->quest_title ? quest->quest_title : "" },
2587  { "text", quest->quest_description ? quest->quest_description : "" },
2588  { "url", "system_quests.html#q" + std::to_string(q) },
2589  };
2590  }
2591 
2592  json["slaying"] = nlohmann::json::array();
2593  for (size_t s = 0; s < slaying_count; s++) {
2594  auto info = slaying_info[s];
2595  json["slaying"].push_back({
2596  { "slaying", info->slaying },
2597  { "doors", create_maps_array(info->maps[S_DOOR]) },
2598  { "keys", create_maps_array(info->maps[S_KEY]) },
2599  { "containers", create_maps_array(info->maps[S_CONTAINER]) },
2600  { "detectors", create_maps_array(info->maps[S_DETECTOR]) },
2601  { "connections", create_maps_array(info->maps[S_CONNECT]) },
2602  });
2603  }
2604 
2605  json["quests"] = nlohmann::json::array();
2606  for (int quest = 0; quest < quests_count; quest++) {
2607  qsort(quests[quest]->maps.list, quests[quest]->maps.count, sizeof(struct_map_in_quest *), sort_struct_map_in_quest);
2608  char buf[100];
2609  snprintf(buf, sizeof(buf), "quest_%d", quests[quest]->number);
2610  json["quests"].push_back(create_quest_object(quests[quest], buf));
2611  }
2612 
2613  json["has_search"] = build_search_file;
2614  if (build_search_file) {
2615  std::string out(root);
2616  out += "/search_data.js";
2617  std::ofstream sf(out, std::ios_base::trunc);
2618  sf << "var search_data = " << search << ";" << std::endl;
2619  sf << "var search_type = { ";
2620  std::string sep;
2621  for (int i = 1; i < int(SearchType::Count); i++) {
2622  sf << sep << i << ": \"" << SearchName[i] << "\"";
2623  sep = ", ";
2624  }
2625  sf << " };" << std::endl;
2626  }
2627 }
2628 
2630 static std::vector<std::string> path_stack;
2631 
2632 void add_template_to_render(const std::string &template_name, const std::string &output_name, const std::string &param);
2633 
2639 static std::string path_from_current(const std::string &path) {
2640  auto p(path);
2641  char rel[1000];
2642  if (p[0] != '/')
2643  p = '/' + p;
2644  auto current(path_stack.back());
2645  if (current[0] != '/')
2646  current = '/' + current;
2647  relative_path(current.c_str(), p.c_str(), rel);
2648  return rel;
2649 }
2650 
2656 static nlohmann::json generate_page_and_link(inja::Arguments &args) {
2657  auto template_name = args.at(0)->get<std::string>();
2658  auto output_name(template_name);
2659  auto param = (args.size() > 1 ? args.at(1)->get<std::string>() : "");
2660 
2661  if (!param.empty()) {
2662  output_name = param + "_" + output_name;
2663  if (param.substr(0, 4) == "map_") {
2664  auto map = find_map_by_key(param);
2665  if (map != nullptr) {
2666  output_name = std::string(map->path + 1) + ".html";
2667  }
2668  }
2669  if (param.substr(0, 4) == "reg_") {
2670  auto reg = find_region_by_key(param);
2671  if (reg != nullptr) {
2672  output_name = std::string(reg->name) + ".html";
2673  }
2674  }
2675  }
2676 
2677  if (template_name != "search_data.js" && template_name != "search_index.js")
2678  add_template_to_render(template_name, output_name, param);
2679  return path_from_current(output_name);
2680 }
2681 
2687 static nlohmann::json generate_picture_link(inja::Arguments &args) {
2688  auto what = args.at(0)->get<std::string>();
2689  if (what.substr(0, 4) == "map_") {
2690  auto map = find_map_by_key(what);
2691  if (map == nullptr)
2692  return "";
2693  int size = 0;
2694  if (args.size() > 1) {
2695  size = args.at(1)->get<int>() - 1;
2696  }
2697  char picpath[1000];
2698  snprintf(picpath, sizeof(picpath), "%s.x%d%s", map->path, size + 1, output_extensions[output_format]);
2699  return path_from_current(picpath);
2700  }
2701  return "";
2702 }
2703 
2708 public:
2709  std::string template_name;
2710  std::string output_name;
2711  std::string param;
2712 };
2713 static std::vector<pageToRender> pages;
2721 void add_template_to_render(const std::string &template_name, const std::string &output_name, const std::string &param) {
2722  auto on(output_name);
2723  if (on[0] != '/')
2724  on = '/' + on;
2725  if (rendered_templates.find(on) != rendered_templates.end())
2726  return;
2727 
2728  rendered_templates.insert(on);
2729  pageToRender r;
2730  r.template_name = template_name;
2731  r.output_name = on;
2732  r.param = param;
2733  pages.push_back(r);
2734 }
2735 
2736 static std::vector<std::string> split(const std::string &field, const std::string &by) {
2737  std::vector<std::string> result;
2738  size_t start = 0, found;
2739  while ((found = field.find(by, start)) != std::string::npos) {
2740  result.push_back(field.substr(start, found - start));
2741  start = found + 1;
2742  }
2743  result.push_back(field.substr(start));
2744  return result;
2745 }
2746 
2747 static std::string templates_root("templates/");
2748 static std::vector<std::string> templates;
2753 static void init_renderer_env() {
2754  env = std::make_shared<inja::Environment>(templates_root, std::string(root) + "/");
2755  env->add_callback("link_to_page", generate_page_and_link);
2756  env->add_callback("substr", [] (inja::Arguments &args) {
2757  std::string str = args.at(0)->get<std::string>();
2758  size_t start = args.at(1)->get<size_t>();
2759  size_t len = args.size() > 2 ? args.at(2)->get<size_t>() : std::string::npos;
2760  return str.substr(start, len);
2761  });
2762  env->add_callback("picture", generate_picture_link);
2763  env->add_callback("pad", [] (inja::Arguments &args) {
2764  char buf[50];
2765  int val = args.at(0)->get<int>(), digits = args.at(1)->get<int>();
2766  snprintf(buf, sizeof(buf), "%0*d", digits, val);
2767  return std::string(buf);
2768  });
2769  env->add_callback("path_to_root", 0, [] (inja::Arguments &) {
2770  std::string root;
2771  auto current(path_stack.back());
2772  if (current[0] == '/')
2773  current = current.substr(1);
2774  size_t start = 0;
2775  while ((start = current.find('/', start)) != std::string::npos) {
2776  start++;
2777  root += "../";
2778  }
2779  return root;
2780  });
2781  env->add_callback("get_by_field", 3, [] (inja::Arguments &args) {
2782  const auto &src = args.at(0);
2783  auto field = args.at(1)->get<std::string>();
2784  const auto &value = args.at(2);
2785  auto found = std::find_if(src->begin(), src->end(), [&field, &value] (auto item) {
2786  return item[field] == *value;
2787  });
2788  if (found == src->end()) {
2789  return nlohmann::json();
2790  }
2791  return *found;
2792  });
2793  env->add_callback("get_list_by_field", 3, [] (inja::Arguments &args) {
2794  nlohmann::json ret = nlohmann::json::array();
2795  const auto &src = args.at(0);
2796  auto field = args.at(1)->get<std::string>();
2797  const auto filter = args.at(2);
2798  if (filter->is_array()) {
2799  std::copy_if(src->begin(), src->end(), std::back_inserter(ret), [&] (auto &item) {
2800  auto val = item[field];
2801  return std::find_if(filter->begin(), filter->end(), [&] (auto li) { return val == li; }) != filter->end();
2802  });
2803  } else {
2804  std::copy_if(src->begin(), src->end(), std::back_inserter(ret), [&] (auto &item) {
2805  return filter->get<std::string>() == item[field];
2806  });
2807  }
2808  return ret;
2809  });
2810  env->add_callback("sort", [] (inja::Arguments &args) {
2811  const auto &src = args.at(0);
2812  std::vector<nlohmann::json> ret;
2813  for (auto i : *src) {
2814  ret.push_back(i);
2815  }
2816  auto fields = split(args.at(1)->get<std::string>(), ",");
2817  bool invert = args.size() > 2 ? args.at(2)->get<bool>() : false;
2818  bool ignore_case = args.size() > 3 ? args.at(3)->get<bool>() : true;
2819  std::sort(ret.begin(), ret.end(), [&] (auto left, auto right) {
2820  for (auto field : fields) {
2821  nlohmann::json l = left[field], r = right[field];
2822  if (ignore_case && l.is_string() && r.is_string()) {
2823  std::string ls(l.get<std::string>()), rs(r.get<std::string>());
2824  std::transform(ls.begin(), ls.end(), ls.begin(), [](unsigned char c){ return std::tolower(c); });
2825  std::transform(rs.begin(), rs.end(), rs.begin(), [](unsigned char c){ return std::tolower(c); });
2826  if (ls == rs) {
2827  continue;
2828  }
2829  return invert ? (rs < ls) : (ls < rs);
2830  }
2831  if (r == l) {
2832  continue;
2833  }
2834  return invert ? (r < l) : (l < r);
2835  }
2836  return false;
2837  });
2838  return ret;
2839  });
2840 
2841  env->set_trim_blocks(true);
2842  env->set_lstrip_blocks(true);
2843 }
2844 
2846 static const char *ignore_path[] = {
2847  "/Info",
2848  "/editor",
2849  "/python",
2850  "/styles",
2851  "/templates",
2852  "/test",
2853  "/unlinked",
2854  NULL };
2855 
2857 static const char *ignore_name[] = {
2858  ".",
2859  "..",
2860  ".git",
2861  ".svn",
2862  "README",
2863  NULL };
2864 
2871 static void find_maps(const char *from) {
2872  struct dirent *file;
2873  struct stat statbuf;
2874  int status, ignore;
2875  char path[1024], full[HUGE_BUF];
2876  DIR *dir;
2877 
2878  for (ignore = 0; ignore_path[ignore] != NULL; ignore++) {
2879  if (strcmp(from, ignore_path[ignore]) == 0)
2880  return;
2881  }
2882 
2883  snprintf(path, sizeof(path), "%s/%s%s", settings.datadir, settings.mapdir, from);
2884  dir = opendir(path);
2885 
2886  if (dir) {
2887  for (file = readdir(dir); file; file = readdir(dir)) {
2888 
2889  for (ignore = 0; ignore_name[ignore] != NULL; ignore++) {
2890  if (strcmp(file->d_name, ignore_name[ignore]) == 0)
2891  break;
2892  }
2893  if (ignore_name[ignore] != NULL)
2894  continue;
2895 
2896  snprintf(full, sizeof(full), "%s/%s", path, file->d_name);
2897 
2898  status = stat(full, &statbuf);
2899  snprintf(full, sizeof(full), "%s/%s", from, file->d_name);
2900  if ((status != -1) && (S_ISDIR(statbuf.st_mode))) {
2901  find_maps(full);
2902  continue;
2903  }
2904  found_maps.push_back(strdup(full));
2905  }
2906  closedir(dir);
2907  }
2908 }
2909 
2911 static void dump_unused_maps(void) {
2912  FILE *dump;
2913  char path[1024];
2914 
2915  snprintf(path, sizeof(path), "%s/%s", root, "maps.unused");
2916  dump = fopen(path, "w+");
2917  if (dump == NULL) {
2918  printf("Unable to open file maps.unused!\n");
2919  return;
2920  }
2921  for (auto map = found_maps.cbegin(); map != found_maps.cend(); ++map) {
2922  fprintf(dump, "%s\n", *map);
2923  }
2924  fclose(dump);
2925  printf("%ld unused maps.\n", found_maps.size());
2926 }
2927 
2929 static void write_world_info(void) {
2930  FILE *file;
2931  char path[strlen(root) + 150 + strlen(output_extensions[output_format])];
2932  int x, y;
2933  gdImagePtr elevationmap;
2934 
2935  if (!world_exit_info)
2936  return;
2937 
2938 
2939  printf("Saving exit/blocking/road information...");
2940  snprintf(path, sizeof(path), "%s/%s%s", root, "world_info", output_extensions[output_format]);
2941  file = fopen(path, "wb+");
2942  save_picture(file, infomap);
2943  fclose(file);
2944  printf("done.\n");
2945  gdImageDestroy(infomap);
2946  infomap = NULL;
2947 
2948  if (elevation_min == 0 || elevation_max == 0) {
2949  puts("Error: Could not save elevation world map due to not finding any minimum or maximum elevation.");
2950  return;
2951  }
2952 
2953  elevationmap = gdImageCreateTrueColor(30*50, 30*50);;
2954 
2955  for (x = 0; x < 30*50; x++) {
2956  for (y = 0; y < 30*50; y++) {
2957  gdImageSetPixel(elevationmap, x, y, get_elevation_color(elevation_info[x][y], elevationmap));
2958  }
2959  }
2960 
2961  printf("Saving elevation world map...");
2962  snprintf(path, sizeof(path), "%s/%s%s", root, "world_elevation", output_extensions[output_format]);
2963  file = fopen(path, "wb+");
2964  save_picture(file, elevationmap);
2965  fclose(file);
2966  printf("done.\n");
2967  gdImageDestroy(elevationmap);
2968  elevationmap = NULL;
2969 }
2970 
2981 static int sort_slaying(const void *left, const void *right) {
2983  struct_slaying_info *r = *(struct_slaying_info **)right;
2984 
2985  return strcasecmp(l->slaying, r->slaying);
2986 }
2987 
2994 static void do_help(const char *program) {
2995  printf("Crossfire Mapper will generate pictures of maps, and create indexes for all maps and regions.\n\n");
2996  printf("Syntax: %s\n\n", program);
2997  printf("Optional arguments:\n");
2998  printf(" -nopics don't generate pictures.\n");
2999  printf(" -root=<path> destination path. Default 'html'.\n");
3000  printf(" -limit=<number> stop processing after this number of maps, -1 to do all maps (default).\n");
3001  printf(" -showmaps outputs the name of maps as they are processed.\n");
3002  printf(" -jpg[=quality] generate jpg pictures, instead of default png. Quality should be 0-95, -1 for automatic.\n");
3003  printf(" -forcepics force to regenerate pics, even if pics's date is after map's.\n");
3004  printf(" -addmap=<map> adds a map to process. Path is relative to map's directory root.\n");
3005  printf(" -rawmaps generates maps pics without items on random (shop, treasure) tiles.\n");
3006  printf(" -warnnopath inform when an exit has no path set.\n");
3007  printf(" -listunusedmaps finds all unused maps in the maps directory.\n");
3008  printf(" -noworldmap don't write the world map in world.png.\n");
3009  printf(" -noregionslink don't generate regions relation file.\n");
3010  printf(" -regionslink generate regions relation file.\n");
3011  printf(" -noexitmap don't generate map of exits.\n");
3012  printf(" -exitmap generate map of exits.\n");
3013  printf(" -tileset=<number> use specified tileset to generate the pictures. Default 0 (standard).\n");
3014  printf(" -details-quests list all quests steps. Default no.\n");
3015  printf(" -list-system-quests include 'system' quests in quest list. Default no.\n");
3016  printf(" -templates-dir=[dir] set the directory to get templates from. Default 'templates/'.\n");
3017  printf(" -add-template=[file] add a template to process. May be specified multiple times. If empty, 'index.html' is used.\n");
3018  printf(" -list-template-to-process display the name of the template about to be rendered. Useful for debugging.");
3019  printf("\n\n");
3020  exit(0);
3021 }
3022 
3031 static void do_parameters(int argc, char **argv) {
3032  int arg = 1;
3033  char path[500];
3034 
3035  root[0] = '\0';
3036 
3037  while (arg < argc) {
3038  if (strcmp(argv[arg], "-nopics") == 0)
3039  generate_pics = 0;
3040  else if (strncmp(argv[arg], "-root=", 6) == 0)
3041  strncpy(root, argv[arg]+6, 500);
3042  else if (strncmp(argv[arg], "-limit=", 7) == 0)
3043  map_limit = atoi(argv[arg]+7);
3044  else if (strcmp(argv[arg], "-showmaps") == 0)
3045  show_maps = 1;
3046  else if (strcmp(argv[arg], "-jpg") == 0) {
3048  if (argv[arg][4] == '=') {
3049  jpeg_quality = atoi(argv[arg]+5);
3050  if (jpeg_quality < 0)
3051  jpeg_quality = -1;
3052  }
3053  }
3054  else if (strcmp(argv[arg], "-forcepics") == 0)
3055  force_pics = 1;
3056  else if (strncmp(argv[arg], "-addmap=", 8) == 0) {
3057  if (*(argv[arg]+8) == '/')
3058  strncpy(path, argv[arg]+8, 500);
3059  else
3060  snprintf(path, 500, "/%s", argv[arg]+8);
3061  add_map(get_map_info(path), &maps_list);
3062  }
3063  else if (strcmp(argv[arg], "-rawmaps") == 0)
3064  rawmaps = 1;
3065  else if (strcmp(argv[arg], "-warnnopath") == 0)
3066  warn_no_path = 1;
3067  else if (strcmp(argv[arg], "-listunusedmaps") == 0)
3068  list_unused_maps = 1;
3069  else if (strcmp(argv[arg], "-noworldmap") == 0)
3070  world_map = 0;
3071  else if (strcmp(argv[arg], "-noregionslink") == 0)
3072  do_regions_link = false;
3073  else if (strcmp(argv[arg], "-regionslink") == 0)
3074  do_regions_link = true;
3075  else if (strcmp(argv[arg], "-noexitmap") == 0)
3076  world_exit_info = 0;
3077  else if (strcmp(argv[arg], "-exitmap") == 0)
3078  world_exit_info = 1;
3079  else if (strncmp(argv[arg], "-tileset=", 9) == 0) {
3080  tileset = atoi(argv[arg]+9);
3081  /* check of validity is done in main() as we need to actually have the sets loaded. */
3082  } else if (strcmp(argv[arg], "-detail-quests") == 0) {
3083  detail_quests = 1;
3084  } else if (strcmp(argv[arg], "-list-system-quests") == 0) {
3085  list_system_quests = 1;
3086  } else if (strncmp(argv[arg], "-templates-dir=", 15) == 0) {
3087  templates_root = argv[arg] + 15;
3088  } else if (strncmp(argv[arg], "-add-template=", 14) == 0) {
3089  templates.push_back(argv[arg] + 14);
3090  } else if (strcmp(argv[arg], "-list-template-to-process") == 0) {
3092  } else if (strncmp(argv[arg], "-build-search-data", 18) == 0) {
3093  build_search_file = true;
3094  } else
3095  do_help(argv[0]);
3096  arg++;
3097  }
3098  if (!strlen(root))
3099  strcpy(root, "html");
3100  if (root[strlen(root)-1] == '/')
3101  root[strlen(root)-1] = '\0';
3102  if (map_limit < -1)
3103  map_limit = -1;
3104 
3105  if (templates_root.empty()) {
3106  templates_root = "templates/";
3107  } else if (templates_root[templates_root.length() - 1] != '/') {
3108  templates_root.append("/");
3109  }
3110 }
3111 
3115 static void create_destination(void) {
3116  char dummy[502];
3117 
3118  strcpy(dummy, root);
3119  strcat(dummy, "/a");
3120  make_path_to_file(dummy);
3121 }
3122 
3131 static const char *yesno(int value) {
3132  return (value ? "yes" : "no");
3133 }
3134 
3135 int main(int argc, char **argv) {
3136  size_t current_map = 0, i;
3137  char max[50];
3138  region *dummy;
3139 
3143  pics_allocated = 0;
3144 
3145  do_parameters(argc, argv);
3146 
3147  printf("Initializing Crossfire data...\n");
3148 
3150 
3151  init_globals();
3152  init_library();
3153  init_readable();
3154 
3155  init_gods();
3156 
3157  /* Add a dummy region so unlinked maps can be identified. */
3158  dummy = get_region_struct();
3159  dummy->fallback = 1;
3160  dummy->name = strdup_local("unlinked");
3161  dummy->longname = strdup_local("This dummy region contains all maps without a region set.");
3162  dummy->longname = strdup_local("This dummy region contains all maps without a region set.");
3163  all_regions.push_back(dummy);
3164 
3165  printf("\n\n done.\n\n");
3166 
3167  if (!is_valid_faceset(tileset)) {
3168  printf("Erreor: invalid tileset %d!\n", tileset);
3169  exit(1);
3170  }
3171 
3172  if (templates.empty()) {
3173  templates.push_back("index.html");
3174  }
3175 
3177  gdfaces.resize(get_faces_count(), nullptr);
3178 
3179  if (map_limit != -1)
3180  snprintf(max, sizeof(max), "%d", map_limit);
3181  else
3182  strcpy(max, "(none)");
3183  printf("Crossfire map browser generator\n");
3184  printf("-------------------------------\n\n");
3185  printf("Parameters:\n");
3186  printf(" path to write files: %s\n", root);
3187  printf(" maximum number of maps to process: %s\n", max);
3188  printf(" will generate map picture: %s\n", yesno(generate_pics));
3189  printf(" will always generate map picture: %s\n", yesno(force_pics));
3190  printf(" picture output format: %s\n", output_extensions[output_format]);
3191  if (output_format == OF_JPG)
3192  printf(" JPEG quality: %d\n", jpeg_quality);
3193  printf(" show map being processed: %s\n", yesno(show_maps));
3194  printf(" generate raw maps: %s\n", yesno(rawmaps));
3195  printf(" warn of exit without path: %s\n", yesno(warn_no_path));
3196  printf(" list unused maps: %s\n", yesno(list_unused_maps));
3197  printf(" generate world map: %s\n", yesno(world_map));
3198  printf(" generate exit map: %s\n", yesno(world_exit_info));
3199  printf(" generate regions link file: %s\n", yesno(do_regions_link));
3200  printf(" tileset: %s\n", find_faceset(tileset)->fullname);
3201  printf(" detail quest steps: %s\n", yesno(detail_quests));
3202  printf(" list system quests: %s\n", yesno(list_system_quests));
3203  printf(" templates directory: %s\n", templates_root.c_str());
3204  printf(" templates to process: ");
3205  const char *sep = "";
3206  for (auto f : templates) {
3207  printf("%s%s", sep, f.c_str());
3208  sep = ", ";
3209  }
3210  printf("\n");
3211  printf(" display template to process: %s\n", yesno(display_rendered_template));
3212  printf("\n");
3213 
3214  if (list_unused_maps) {
3215  printf("listing all maps...");
3216  find_maps("");
3217  printf("done, %ld maps found.\n", found_maps.size());
3218  }
3219 
3220  /* exit/blocking information. */
3221  infomap = gdImageCreateTrueColor(30*50, 30*50);
3222  color_unlinked_exit = gdImageColorResolve(infomap, 255, 0, 0);
3223  color_linked_exit = gdImageColorResolve(infomap, 255, 255, 255);
3224  color_road = gdImageColorResolve(infomap, 0, 255, 0);
3225  color_blocking = gdImageColorResolve(infomap, 0, 0, 255);
3226  color_slowing = gdImageColorResolve(infomap, 0, 0, 127);
3227  elevation_info = (int **)calloc(50*30, sizeof(int *));
3228  for (i = 0; i < 50*30; i++)
3229  elevation_info[i] = (int *)calloc(50*30, sizeof(int));
3230  elevation_min = 0;
3231  elevation_max = 0;
3232 
3233  printf("browsing maps...\n");
3234 
3236 
3237  while (current_map < maps_list.count) {
3238  process_map(maps_list.maps[current_map++]);
3239  if (current_map%100 == 0) {
3240  printf(" %zu maps processed, %d map pictures created, %d map pictures were uptodate. %d faces used.\n", current_map, created_pics, cached_pics, pics_allocated);
3241  }
3242  if ((map_limit != -1) && (current_map == static_cast<size_t>(map_limit))) {
3243  printf(" --- map limit reached, stopping ---\n");
3244  break;
3245  }
3246  }
3247 
3248  printf(" finished map parsing, %zu maps processed, %d map pictures created, %d map pictures were uptodate. Total %d faces used.\n", current_map, created_pics, cached_pics, pics_allocated);
3249 
3250  if (list_unused_maps)
3251  dump_unused_maps();
3252 
3254  fix_map_names();
3255  fix_tiled_map();
3257  write_tiled_maps();
3258 
3259  write_world_map();
3260  write_world_info();
3261 
3263  qsort(regions, region_count, sizeof(struct_region_info *), sort_region);
3264  std::sort(special_equipment.begin(), special_equipment.end(), sort_equipment);
3266  qsort(races.races, races.count, sizeof(struct_race *), sort_race);
3267  qsort(quests, quests_count, sizeof(struct_quest *), sort_struct_quest);
3268 
3270  std::sort(system_quests.begin(), system_quests.end(), [] (const auto &left, const auto &right) { return strcmp(left->quest_code, right->quest_code) < 0; });
3271 
3273 
3275 
3276  for (auto file : templates) {
3277  if (!file.empty()) {
3278  add_template_to_render(file, file, "");
3279  }
3280  }
3281 
3282  const auto fullStart = time(nullptr);
3283  printf("rendering pages...");
3285  printf("\n");
3286  fflush(stdout);
3287 
3288  while (!pages.empty()) {
3289  auto p = pages.back();
3290  pages.pop_back();
3291  if (p.param.empty())
3292  all_data.erase("param");
3293  else
3294  all_data["param"] = p.param;
3295  const auto start = time(nullptr);
3297  printf(" rendering page %s (%s)... ", p.template_name.c_str(), p.param.c_str());
3298  fflush(stdout);
3299  }
3300  path_stack.push_back(p.output_name);
3301  inja::Template temp = get_template(p.template_name);
3302  env->write(temp, all_data, p.output_name);
3303  path_stack.pop_back();
3304  const auto elapsed = time(nullptr) - start;
3306  printf("took %ld seconds\n", elapsed);
3307  }
3308  }
3309 
3310  const auto elapsed = time(nullptr) - fullStart;
3311  printf(" done, took %ld seconds\n", elapsed);
3312 
3313  return 0;
3314 }
3315 
3317  int x, y;
3318 
3319  if (m == NULL)
3320  return;
3321 
3322  for (x = 0; x < MAP_WIDTH(m); x++)
3323  for (y = 0; y < MAP_HEIGHT(m); y++)
3324  FOR_MAP_PREPARE(m, x, y, tmp) {
3325  if (tmp->inv) {
3326  FOR_INV_PREPARE(tmp, invtmp) {
3327  if (QUERY_FLAG(invtmp, FLAG_AUTO_APPLY))
3328  apply_auto(invtmp);
3329  else if (invtmp->type == TREASURE && HAS_RANDOM_ITEMS(invtmp)) {
3330  while ((invtmp->stats.hp--) > 0)
3331  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
3332  invtmp->randomitems = NULL;
3333  } else if (invtmp
3334  && invtmp->arch
3335  && invtmp->type != TREASURE
3336  && invtmp->type != SPELL
3337  && invtmp->type != CLASS
3338  && HAS_RANDOM_ITEMS(invtmp)) {
3339  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
3340  /* Need to clear this so that we never try to create
3341  * treasure again for this object
3342  */
3343  invtmp->randomitems = NULL;
3344  }
3345  } FOR_INV_FINISH();
3346  /* This is really temporary - the code at the bottom will
3347  * also set randomitems to null. The problem is there are bunches
3348  * of maps/players already out there with items that have spells
3349  * which haven't had the randomitems set to null yet.
3350  * MSW 2004-05-13
3351  *
3352  * And if it's a spellbook, it's better to set randomitems to NULL too,
3353  * else you get two spells in the book ^_-
3354  * Ryo 2004-08-16
3355  */
3356  if (tmp->type == WAND
3357  || tmp->type == ROD
3358  || tmp->type == SCROLL
3359  || tmp->type == FIREWALL
3360  || tmp->type == POTION
3361  || tmp->type == ALTAR
3362  || tmp->type == SPELLBOOK)
3363  tmp->randomitems = NULL;
3364  }
3365 
3366  if (QUERY_FLAG(tmp, FLAG_AUTO_APPLY))
3367  apply_auto(tmp);
3368  else if ((tmp->type == TREASURE || (tmp->type == CONTAINER)) && HAS_RANDOM_ITEMS(tmp)) {
3369  while ((tmp->stats.hp--) > 0)
3370  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
3371  tmp->randomitems = NULL;
3372  } else if (tmp->type == TIMED_GATE) {
3373  object *head = HEAD(tmp);
3374 
3375  if (QUERY_FLAG(head, FLAG_IS_LINKED)) {
3376  tmp->speed = 0;
3377  object_update_speed(tmp);
3378  }
3379  /* This function can be called everytime a map is loaded, even when
3380  * swapping back in. As such, we don't want to create the treasure
3381  * over and ove again, so after we generate the treasure, blank out
3382  * randomitems so if it is swapped in again, it won't make anything.
3383  * This is a problem for the above objects, because they have counters
3384  * which say how many times to make the treasure.
3385  */
3386  } else if (tmp
3387  && tmp->arch
3388  && tmp->type != PLAYER
3389  && tmp->type != TREASURE
3390  && tmp->type != SPELL
3391  && tmp->type != PLAYER_CHANGER
3392  && tmp->type != CLASS
3393  && HAS_RANDOM_ITEMS(tmp)) {
3394  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
3395  tmp->randomitems = NULL;
3396  }
3397  } FOR_MAP_FINISH();
3398 
3399  for (x = 0; x < MAP_WIDTH(m); x++)
3400  for (y = 0; y < MAP_HEIGHT(m); y++)
3401  FOR_MAP_PREPARE(m, x, y, tmp) {
3402  if (tmp->above
3403  && (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL))
3404  check_trigger(tmp, tmp->above);
3405  } FOR_MAP_FINISH();
3406 }
3407 
3408 #ifndef DOXYGEN_SHOULD_SKIP_THIS
3409 
3414 void draw_ext_info(int, int, const object *, uint8_t, uint8_t, const char *txt) {
3415  fprintf(logfile, "%s\n", txt);
3416 }
3417 
3418 void draw_ext_info_format(int, int, const object *, uint8_t, uint8_t, const char *format, ...) {
3419  va_list ap;
3420 
3421  va_start(ap, format);
3422  vfprintf(logfile, format, ap);
3423  va_end(ap);
3424 }
3425 
3426 void ext_info_map(int, const mapstruct *, uint8_t, uint8_t, const char *str1) {
3427  fprintf(logfile, "ext_info_map: %s\n", str1);
3428 }
3429 
3430 void move_firewall(object *) {
3431 }
3432 
3433 void emergency_save(int) {
3434 }
3435 
3436 void clean_tmp_files(void) {
3437 }
3438 
3439 void esrv_send_item(object *, object *) {
3440 }
3441 
3442 void dragon_ability_gain(object *, int, int) {
3443 }
3444 
3445 void set_darkness_map(mapstruct *) {
3446 }
3447 
3448 object *find_skill_by_number(object *, int) {
3449  return NULL;
3450 }
3451 
3452 void esrv_del_item(player *, object *) {
3453 }
3454 
3455 void esrv_update_item(int, object *, object *) {
3456 }
3457 
3458 void esrv_update_spells(player *) {
3459 }
3460 
3461 void rod_adjust(object *) {
3462 }
3463 
3464 /*
3465  * This a modified version of apply_auto: BOOK are not generated, so they don't pollute
3466  * the readable list.
3467  */
3468 int apply_auto(object *op) {
3469  object *tmp = NULL;
3470  int i;
3471 
3472  switch (op->type) {
3473  case SHOP_FLOOR:
3474  if (!HAS_RANDOM_ITEMS(op))
3475  return 0;
3476  do {
3477  i = 10; /* let's give it 10 tries */
3478  while ((tmp = generate_treasure(op->randomitems, op->stats.exp ? (int)op->stats.exp : MAX(op->map->difficulty, 5))) == NULL && --i)
3479  ;
3480  if (tmp == NULL)
3481  return 0;
3482  if (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED) || tmp->type == BOOK) {
3484  tmp = NULL;
3485  }
3486  } while (!tmp);
3487  SET_FLAG(tmp, FLAG_UNPAID);
3488  object_insert_in_map_at(tmp, op->map, NULL, 0, op->x, op->y);
3490  tmp = identify(tmp);
3491  break;
3492 
3493  case TREASURE:
3494  if (QUERY_FLAG(op, FLAG_IS_A_TEMPLATE))
3495  return 0;
3496 
3497  while ((op->stats.hp--) > 0)
3498  create_treasure(op->randomitems, op, 0, op->stats.exp ? (int)op->stats.exp : op->map == NULL ? 14 : op->map->difficulty, 0);
3499 
3500  /* If we generated an object and put it in this object inventory,
3501  * move it to the parent object as the current object is about
3502  * to disappear. An example of this item is the random_ *stuff
3503  * that is put inside other objects.
3504  */
3505  FOR_INV_PREPARE(op, tmp) {
3506  object_remove(tmp);
3507  if (op->env && tmp->type != BOOK)
3508  object_insert_in_ob(tmp, op->env);
3509  else
3511  }
3512  FOR_INV_FINISH();
3513  object_remove(op);
3515  break;
3516  }
3517  return tmp ? 1 : 0;
3518 }
3519 
3520 void apply_auto_fix(mapstruct *) {
3521 }
3522 
3524  return NULL;
3525 }
3526 
3527 player *find_player_partial_name(const char *) {
3528  return NULL;
3529 }
3530 
3531 Account_Chars *account_char_load(const char *) {
3532  return NULL;
3533 }
3534 
3536 }
3537 
3539 }
3540 
3541 void command_help(object *, const char *) {
3542 }
3543 
3544 void account_logout(const char *) {
3545 }
3546 
3547 #endif /* dummy DOXYGEN_SHOULD_SKIP_THIS */
get_race
static struct_race * get_race(const char *name)
Returns the race for specified name.
Definition: mapper.cpp:648
struct_map_info::tiles
struct struct_map_info * tiles[4]
Definition: mapper.cpp:262
CLASS
@ CLASS
Object for applying character class modifications to someone.
Definition: object.h:143
object::name_pl
sstring name_pl
The plural name of the object.
Definition: object.h:323
struct_region_info::sum_x
int sum_x
Definition: mapper.cpp:408
init_globals
void init_globals(void)
Initialises all global variables.
Definition: init.cpp:385
write_tiled_map_page
static void write_tiled_map_page(struct_map_info *map)
Writes the page for a tiled map group.
Definition: mapper.cpp:2197
fix_tiled_map_monsters
static void fix_tiled_map_monsters(void)
Makes all monsters point to tiled maps instead of map when appliable, and merge map monster to tiled ...
Definition: mapper.cpp:2032
do_auto_apply
void do_auto_apply(mapstruct *m)
Definition: mapper.cpp:3316
add_map
static void add_map(struct_map_info *info, struct_map_list *list)
Adds a map to specified array, if it isn't already.
Definition: mapper.cpp:1220
living::exp
int64_t exp
Experience.
Definition: living.h:47
HAS_RANDOM_ITEMS
#define HAS_RANDOM_ITEMS(op)
This return TRUE if object has still randomitems which could be expanded.
Definition: define.h:184
PLAYER
@ PLAYER
Definition: object.h:112
Settings::mapdir
const char * mapdir
Where the map files are.
Definition: global.h:256
global.h
settings
struct Settings settings
Global settings.
Definition: init.cpp:139
ignore_name
static const char * ignore_name[]
File names to ignore for map search.
Definition: mapper.cpp:2857
struct_equipment::diff
char * diff
Result of get_ob_diff() with the item's clone.
Definition: mapper.cpp:276
get_quest_info
static struct_quest * get_quest_info(const char *name)
Gets the information for a quest, create the field if needed.
Definition: mapper.cpp:987
find_region_by_key
static region * find_region_by_key(const std::string &key)
Get the region with the specified key, nullptr if not found.
Definition: mapper.cpp:2247
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:714
emergency_save
void emergency_save(int flag)
Save all players.
Definition: main.cpp:347
process_map_lore
static void process_map_lore(struct_map_info *map)
Extracts from the map's lore quest information if found.
Definition: mapper.cpp:1101
find_artifact
const artifact * find_artifact(const object *op, const char *name)
Searches and returns a specific artifact compatible with an object, NULL if not found.
Definition: artifact.cpp:585
llevError
@ llevError
Error, serious thing.
Definition: logger.h:11
get_region_struct
region * get_region_struct(void)
Allocates and zeros a region struct, this isn't free()'d anywhere, so might be a memory leak,...
Definition: region.cpp:293
mapstruct::difficulty
uint16_t difficulty
What level the player should be to play here.
Definition: map.h:338
region::fallback
int8_t fallback
Whether, in the event of a region not existing, this should be the one we fall back on as the default...
Definition: map.h:290
compare_map_info
static int compare_map_info(const struct_map_info *left, const struct_map_info *right)
Compares struct_map_info according to the map name or the path if equal.
Definition: mapper.cpp:875
path_from_current
static std::string path_from_current(const std::string &path)
Compute the relative path from the specified file to the current file.
Definition: mapper.cpp:2639
find_skill_by_number
object * find_skill_by_number(object *who, int skillno)
This returns the first skill pointer of the given subtype (the one that accumulates exp,...
Definition: main.cpp:381
WAND
@ WAND
Definition: object.h:225
quest_for_each
void quest_for_each(quest_op op, void *user)
Iterate over all quests.
Definition: assets.cpp:543
LOG
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
struct_region_info::is_world
int is_world
If set, this region has at least one map part of the world, thus region name should be written.
Definition: mapper.cpp:409
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:369
generate_picture_link
static nlohmann::json generate_picture_link(inja::Arguments &args)
Return the link to the picture of the specified item.
Definition: mapper.cpp:2687
struct_map_info::tiled_group
struct struct_map_info * tiled_group
Definition: mapper.cpp:259
build_search_file
static bool build_search_file
If set, will build the 'search_data.js' file.
Definition: mapper.cpp:374
struct_map_info::filename
char * filename
Filename of the map.
Definition: mapper.cpp:243
num_sizes
static const int num_sizes
Definition: mapper.cpp:363
player
One player.
Definition: player.h:107
add_slaying
static void add_slaying(struct_map_info *map, object *item)
Adds the item's information to the map.
Definition: mapper.cpp:1484
SearchType::Region
@ Region
FLAG_IS_LINKED
#define FLAG_IS_LINKED
The object is linked with other objects.
Definition: define.h:302
strdup_local
#define strdup_local
Definition: compat.h:29
ready_map_name
mapstruct * ready_map_name(const char *name, int flags)
Makes sure the given map is loaded and swapped in.
Definition: map.cpp:1780
write_tiled_maps
static void write_tiled_maps(void)
Outputs all tiled map pages.
Definition: mapper.cpp:2207
first_map_path
char first_map_path[MAX_BUF]
The start-level.
Definition: init.cpp:120
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:371
struct_quest::maps
struct_map_in_quest_list maps
Maps part of this quest.
Definition: mapper.cpp:942
create_quest_object
static nlohmann::json create_quest_object(struct_quest *quest, const std::string &key)
Return a JSON quest object.
Definition: mapper.cpp:2363
create_map_info
static struct_map_info * create_map_info(void)
Returns an initialised struct_map_info.
Definition: mapper.cpp:1241
struct_race::count
int count
Number found on map.
Definition: mapper.cpp:286
TRIGGER_PEDESTAL
@ TRIGGER_PEDESTAL
Definition: object.h:139
struct_map_in_quest::map
struct_map_info * map
Linked map.
Definition: mapper.cpp:933
pageToRender::param
std::string param
Optional template parameter.
Definition: mapper.cpp:2711
S_CONNECT
#define S_CONNECT
Definition: mapper.cpp:441
write_pictures_from_real_size
static void write_pictures_from_real_size(const char *path, gdImagePtr real, int width, int height)
Definition: mapper.cpp:1524
region_links
static std::map< region *, std::set< region * > > region_links
Definition: mapper.cpp:434
get_face_fallback
int get_face_fallback(int faceset, uint16_t imageno)
This returns the set we will actually use when sending a face.
Definition: image.cpp:133
object::item_power
int8_t item_power
Power rating of the object.
Definition: object.h:372
Settings::datadir
const char * datadir
Read only data files.
Definition: global.h:253
c
static event_registration c
Definition: citylife.cpp:424
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:233
object::arch
struct archetype * arch
Pointer to archetype.
Definition: object.h:424
output_format
static enum output_format_type output_format
Selected output format.
Definition: mapper.cpp:393
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.cpp:57
IS_WEAPON
#define IS_WEAPON(op)
Definition: define.h:163
quests_count
static int quests_count
Count of quests.
Definition: mapper.cpp:947
SHOP_FLOOR
@ SHOP_FLOOR
Definition: object.h:188
create_npc_array
static nlohmann::json create_npc_array(npc_list &list)
Return an array of NPC information.
Definition: mapper.cpp:2275
get_map_info
static struct_map_info * get_map_info(const char *path)
Gets or creates if required the info structure for a map.
Definition: mapper.cpp:1313
EXIT_PATH
#define EXIT_PATH(xyz)
Definition: define.h:424
fix_exits_to_tiled_maps
static void fix_exits_to_tiled_maps(void)
Changes all exits to maps in a tiled map to point directly to the tiled map.
Definition: mapper.cpp:2004
object::x
int16_t x
Definition: object.h:335
reverse_maps
static std::map< struct_map_info *, std::string > reverse_maps
Link between a map and its unique identifier.
Definition: mapper.cpp:2227
dump
static int dump(const std::set< std::string > &items, const char *name)
Definition: AssetsManager.cpp:42
gdfaces
static std::vector< gdImagePtr > gdfaces
Definition: mapper.cpp:206
struct_map_in_quest
Link between a quest and a map.
Definition: mapper.cpp:930
slaying_allocated
static size_t slaying_allocated
Allocated size of slaying_info.
Definition: mapper.cpp:452
give_artifact_abilities
void give_artifact_abilities(object *op, const object *artifact)
Fixes the given object, giving it the abilities and titles it should have due to the second artifact-...
Definition: artifact.cpp:230
MAP_IN_MEMORY
#define MAP_IN_MEMORY
Map is fully loaded.
Definition: map.h:131
object::map
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
get_equipment
static struct_equipment * get_equipment(void)
Gets an empty struct_equipment.
Definition: mapper.cpp:486
is_special_equipment
static int is_special_equipment(object *item)
Definition: mapper.cpp:467
TIMED_GATE
@ TIMED_GATE
Definition: object.h:133
region_allocated
static size_t region_allocated
Allocated size of regions.
Definition: mapper.cpp:414
struct_map_list
List of maps.
Definition: mapper.cpp:233
generate_page_and_link
static nlohmann::json generate_page_and_link(inja::Arguments &args)
Create a link to a page, generating it if needed.
Definition: mapper.cpp:2656
struct_equipment::origin
struct_map_list origin
Map(s) this item is found in.
Definition: mapper.cpp:277
generate_treasure
object * generate_treasure(treasurelist *t, int difficulty)
Generate a treasure from a list generating a single item.
Definition: treasure.cpp:319
fields
non standard information is not specified or uptime fields
Definition: arch-handbook.txt:204
find_faceset
face_sets * find_faceset(int id)
Definition: assets.cpp:332
artifact::item
object * item
Special values of the artifact.
Definition: artifact.h:15
root
static char root[500]
Path to store generated files.
Definition: mapper.cpp:354
create_map_in_quest_array
static nlohmann::json create_map_in_quest_array(struct_map_in_quest_list &list)
Return an array of map-in-quest items.
Definition: mapper.cpp:2311
time
non standard information is not specified or uptime this means how long since the executable has been started A particular host may have been running a server for quite a long time
Definition: arch-handbook.txt:206
yesno
static const char * yesno(int value)
Helper to write yes/no.
Definition: mapper.cpp:3131
AMULET
@ AMULET
Definition: object.h:144
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
CHECK_INV
@ CHECK_INV
b.t.
Definition: object.h:174
struct_map_info::name
char * name
Map's name as defined in the map file.
Definition: mapper.cpp:242
fix_map_names
static void fix_map_names(void)
Ensures all maps have a name (if there was a limit to map processing, some maps will have a NULL name...
Definition: mapper.cpp:1898
struct_slaying_info::maps
struct_map_list maps[S_MAX]
Definition: mapper.cpp:447
MIN
#define MIN(x, y)
Definition: compat.h:21
SIZE
#define SIZE
maps_list
static struct_map_list maps_list
Maps to process or found.
Definition: mapper.cpp:266
TREASURE
@ TREASURE
Definition: object.h:115
color_unlinked_exit
static int color_unlinked_exit
Color for exits without a path set.
Definition: mapper.cpp:421
Region
One region with bells.
Definition: cfcitybell.cpp:38
struct_region_info::sum_y
int sum_y
Definition: mapper.cpp:408
pages
static std::vector< pageToRender > pages
List of pages to render.
Definition: mapper.cpp:2713
list_unused_maps
static int list_unused_maps
If set, program will list maps found in directory but not linked from the first maps.
Definition: mapper.cpp:416
SearchType::Monster
@ Monster
esrv_update_spells
void esrv_update_spells(player *pl)
This looks for any spells the player may have that have changed their stats.
Definition: main.cpp:392
struct_map_info
Map information.
Definition: mapper.cpp:240
struct_map_info::min_monster
int min_monster
Definition: mapper.cpp:246
FREE_OBJ_FREE_INVENTORY
#define FREE_OBJ_FREE_INVENTORY
Free inventory objects; if not set, drop inventory.
Definition: object.h:544
create_region_array
static nlohmann::json create_region_array(const std::set< region * > &regions)
Return an array of region identifiers.
Definition: mapper.cpp:2407
struct_region_info
Region information.
Definition: mapper.cpp:405
add_npc_to_map
static void add_npc_to_map(npc_list *list, const object *npc)
Add the specified NPC to the list.
Definition: mapper.cpp:1204
rod_adjust
void rod_adjust(object *rod)
Adjusts rod attributes.
Definition: main.cpp:396
monster
the faster the spell may be cast there are several other common only the caster may be affected by the spell The most common spell range is that of touch This denotes that the caster much touch the recipient of the spell in order to release the spell monster
Definition: spell-info.txt:45
region::name
char * name
Shortend name of the region as maps refer to it.
Definition: map.h:280
SIGN
@ SIGN
Definition: object.h:216
struct_equipment::name
char * name
Item's name.
Definition: mapper.cpp:273
TRIGGER_BUTTON
@ TRIGGER_BUTTON
Definition: object.h:137
object::title
sstring title
Of foo, etc.
Definition: object.h:325
FLAG_CURSED
#define FLAG_CURSED
The object is cursed.
Definition: define.h:303
mapstruct::path
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:361
struct_map_info::max_monster
int max_monster
Definition: mapper.cpp:246
quest_definition::quest_is_system
bool quest_is_system
If set then the quest isn't counted or listed.
Definition: quest.h:45
struct_slaying_info
slaying information.
Definition: mapper.cpp:445
buf
StringBuffer * buf
Definition: readable.cpp:1564
struct_equipment::calc_power
int calc_power
Item power calculated via calc_item_power().
Definition: mapper.cpp:275
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
Definition: object.cpp:2842
HUGE_BUF
#define HUGE_BUF
Used for messages - some can be quite long.
Definition: define.h:37
MAX
#define MAX(x, y)
Definition: compat.h:24
SearchType
SearchType
Search values, for the JS search engine.
Definition: mapper.cpp:295
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
force_pics
static int force_pics
To force picture regeneration even if map didn't change.
Definition: mapper.cpp:361
world_exit_info
static int world_exit_info
If set, will generate a world map of exits.
Definition: mapper.cpp:369
draw_ext_info
vs only yadda is in because all tags get reset on the next draw_ext_info In the second since it is all in one draw_ext_info
Definition: media-tags.txt:61
sort_struct_quest
static int sort_struct_quest(const void *left, const void *right)
Sorts 2 struct_quest, on the map's name or path.
Definition: mapper.cpp:1066
struct_quest
One quest.
Definition: mapper.cpp:937
dragon_ability_gain
void dragon_ability_gain(object *who, int atnr, int level)
When a dragon-player gains a new stage of evolution, he gets some treasure.
Definition: main.cpp:365
struct_map_in_quest_list
Utility structure to group map-quest link structure.
Definition: mapper.cpp:226
region::longname
char * longname
Official title of the region, this might be defined to be the same as name.
Definition: map.h:286
struct_region_info::reg
region * reg
Region.
Definition: mapper.cpp:406
esrv_send_item
void esrv_send_item(object *pl, object *op)
Sends item's info to player.
Definition: main.cpp:354
SearchType::Quest
@ Quest
struct_map_in_quest::quest
struct struct_quest * quest
Point back to the quest.
Definition: mapper.cpp:935
init_renderer_env
static void init_renderer_env()
Initialize env and set various callbacks and options.
Definition: mapper.cpp:2753
struct_quest::description
char * description
Description, from the main map's lore.
Definition: mapper.cpp:939
init_gods
void init_gods(void)
This takes a look at all of the archetypes to find the objects which correspond to the GODS (type GOD...
Definition: holy.cpp:59
object::y
int16_t y
Position in the map for this object.
Definition: object.h:335
m
static event_registration m
Definition: citylife.cpp:424
set_darkness_map
void set_darkness_map(mapstruct *m)
Set the darkness level for a map, based on the time of the day.
Definition: main.cpp:371
MOVE_ALL
#define MOVE_ALL
Mask of all movement types.
Definition: define.h:389
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.cpp:76
apply_auto_fix
void apply_auto_fix(mapstruct *m)
Go through the entire map (only the first time when an original map is loaded) and performs special a...
Definition: main.cpp:258
S_CONTAINER
#define S_CONTAINER
Definition: mapper.cpp:439
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects,...
Definition: object.cpp:1545
opendir
DIR * opendir(const char *)
struct_map_info::reset_group
sstring reset_group
Definition: mapper.cpp:250
templateCache
static inja::TemplateStorage templateCache
Definition: mapper.cpp:2418
regions
static struct struct_region_info ** regions
Found regions.
Definition: mapper.cpp:412
struct_npc_info::y
int y
Coordinates in the map.
Definition: mapper.cpp:212
struct_map_info::exits_from
struct_map_list exits_from
Definition: mapper.cpp:247
Settings::debug
LogLevel debug
Default debugging level.
Definition: global.h:248
detail_quests
static bool detail_quests
Whether to show all quests details or not.
Definition: mapper.cpp:371
ensure_unique
static struct_equipment * ensure_unique(struct_equipment *item)
Searches the item list for an identical item, except maps.
Definition: mapper.cpp:533
struct_npc_info::message
const char * message
NPC's message.
Definition: mapper.cpp:211
get_slaying_struct
static struct_slaying_info * get_slaying_struct(const char *slaying)
Returns a struct_slaying_info for specified slaying.
Definition: mapper.cpp:1441
generate_picture_path
static void generate_picture_path(const char *path, size_t pic_size, char *out, size_t len)
Definition: mapper.cpp:1520
OF_JPG
@ OF_JPG
JPG.
Definition: mapper.cpp:383
elevation_max
static int elevation_max
Lowest elevation found.
Definition: mapper.cpp:429
struct_map_info::pic_was_done
int pic_was_done
Definition: mapper.cpp:246
FLAG_UNPAID
#define FLAG_UNPAID
Object hasn't been paid for yet.
Definition: define.h:223
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Do not run the destroy callback.
Definition: object.h:545
POTION
@ POTION
Definition: object.h:116
struct_npc_info
Information about a NPC with a custom message.
Definition: mapper.cpp:209
define_quest
static void define_quest(const char *name, struct_map_info *mainmap, const char *description)
Sets the main map for a quest.
Definition: mapper.cpp:1082
path_combine_and_normalize
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Combines the 2 paths.
Definition: path.cpp:172
add_to_struct_map_in_quest_list
static void add_to_struct_map_in_quest_list(struct_map_in_quest_list *list, struct_map_in_quest *item)
Definition: mapper.cpp:957
do_tiled_map_picture
static void do_tiled_map_picture(struct_map_info *map)
Generates the large and small pictures for a tiled map.
Definition: mapper.cpp:2089
account_char_free
void account_char_free(Account_Chars *chars)
This frees all data associated with the character information.
Definition: account_char.cpp:345
archetype::clone
object clone
An object from which to do object_copy()
Definition: object.h:487
slaying_info
static struct_slaying_info ** slaying_info
Found slaying fields.
Definition: mapper.cpp:450
add_string
sstring add_string(const char *str)
Share a string.
Definition: shstr.cpp:137
FLAG_MONSTER
#define FLAG_MONSTER
Will attack players.
Definition: define.h:232
races
static struct_race_list races
Monsters found in maps.
Definition: mapper.cpp:290
npc_list
std::vector< struct_npc_info * > npc_list
List of NPCs with a custom message.
Definition: mapper.cpp:216
object_get_multi_size
void object_get_multi_size(const object *ob, int *sx, int *sy, int *hx, int *hy)
Computes the size of a multitile object.
Definition: object.cpp:4729
main
int main(int argc, char **argv)
Definition: mapper.cpp:3135
HEAD
#define HEAD(op)
Returns the head part of an object.
Definition: object.h:607
output_extensions
static const char * output_extensions[]
Extensions depending on output format.
Definition: mapper.cpp:387
create_maps_array
static nlohmann::json create_maps_array(struct_map_list &maps)
Return an array of map identifiers.
Definition: mapper.cpp:2259
ROD
@ ROD
Definition: object.h:114
show_maps
static int show_maps
If set, will generate much information on map loaded.
Definition: mapper.cpp:367
CONTAINER
@ CONTAINER
Definition: object.h:236
system_quests
static std::vector< quest_definition * > system_quests
Definition: mapper.cpp:2216
FLAG_UNAGGRESSIVE
#define FLAG_UNAGGRESSIVE
Monster doesn't attack players.
Definition: define.h:259
get_elevation_color
static int get_elevation_color(int elevation, gdImagePtr elevationmap)
Gets the color for an elevation.
Definition: mapper.cpp:762
reset_groups
static std::set< std::string > reset_groups
All defined reset groups.
Definition: mapper.cpp:292
region::msg
char * msg
The description of the region.
Definition: map.h:288
init_readable
void init_readable(void)
Initialize linked lists utilized by message functions in tailor_readable_ob()
Definition: readable.cpp:904
S_MAX
#define S_MAX
Definition: mapper.cpp:442
quest_callback
static void quest_callback(const quest_definition *quest, void *)
Definition: mapper.cpp:2218
readdir
struct dirent * readdir(DIR *)
ext_info_map
void void ext_info_map(int color, const mapstruct *map, uint8_t type, uint8_t subtype, const char *str1)
Writes to everyone on the specified map.
Definition: main.cpp:334
LOCKED_DOOR
@ LOCKED_DOOR
Definition: object.h:128
struct_race::name
char * name
Monster's name.
Definition: mapper.cpp:285
is_slaying
static int is_slaying(object *item)
Is the slaying field relevant for this item?
Definition: mapper.cpp:1428
struct_equipment::power
int power
Item power as declared by the item itself.
Definition: mapper.cpp:274
create_race_array
static nlohmann::json create_race_array(struct_race_list &list)
Return an array of monster information.
Definition: mapper.cpp:2294
description
spell prayer lvl t sp speed range duration short description
Definition: spell-summary.txt:2
SPECIAL_KEY
@ SPECIAL_KEY
Definition: object.h:129
object_update_speed
void object_update_speed(object *op)
Updates the speed of an object.
Definition: object.cpp:1334
struct_race::origin
struct_map_list origin
Maps to find said monster.
Definition: mapper.cpp:287
color_slowing
static int color_slowing
Slows movement.
Definition: mapper.cpp:425
object::type
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
struct_map_info::quests
struct_map_in_quest_list quests
Definition: mapper.cpp:249
write_world_map
static void write_world_map(void)
Generates a big world map.
Definition: mapper.cpp:1795
struct_map_info::width
int width
Definition: mapper.cpp:260
command_help
void command_help(object *op, const char *params)
Player is asking for some help.
Definition: c_misc.cpp:1772
add_map_to_quest
static void add_map_to_quest(struct_map_info *map, const char *name, const char *description)
Links a map to a quest.
Definition: mapper.cpp:1016
create_npc_info
static struct_npc_info * create_npc_info(const object *npc)
Create the struct_npc_info from the specified NPC.
Definition: mapper.cpp:1186
face_info::data
uint8_t * data
Image data.
Definition: image.h:11
move_firewall
void move_firewall(object *op)
Move for FIREWALL.
Definition: main.cpp:343
color_road
static int color_road
Road or equivalent.
Definition: mapper.cpp:423
tileset
static int tileset
Tileset to use to generate pics.
Definition: mapper.cpp:370
object_free
void object_free(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects,...
Definition: object.cpp:1577
FOR_INV_FINISH
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:661
is_blocking
static int is_blocking(object *item)
Checks if item blocks movement or not.
Definition: mapper.cpp:748
FLAG_NO_PICK
#define FLAG_NO_PICK
Object can't be picked up.
Definition: define.h:226
do_exit_map
static void do_exit_map(mapstruct *map)
Proceses exit / road / blocking information for specified map into the global infomap map.
Definition: mapper.cpp:779
create_destination
static void create_destination(void)
Ensures destination directory exists.
Definition: mapper.cpp:3115
struct_map_info::tiled_y_from
int tiled_y_from
Definition: mapper.cpp:261
struct_race_list::races
struct struct_race ** races
Races on the list.
Definition: mapper.cpp:220
check_slaying_inventory
static void check_slaying_inventory(struct_map_info *map, object *item)
Recursively checks if the object should be considered for slaying information.
Definition: mapper.cpp:1512
FLAG_IS_A_TEMPLATE
#define FLAG_IS_A_TEMPLATE
Object has no ingame life until instantiated.
Definition: define.h:353
archetype
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
Definition: object.h:483
jpeg_quality
static int jpeg_quality
Quality for jpg pictures.
Definition: mapper.cpp:396
sproto.h
append_map_list
static void append_map_list(struct_map_list &dest, struct_map_list &src)
Append the contents of src to dest.
Definition: mapper.cpp:2397
struct_map_info::npcs
npc_list * npcs
Definition: mapper.cpp:256
logfile
FILE * logfile
Used by server/daemon.c.
Definition: init.cpp:114
FLAG_IS_FLOOR
#define FLAG_IS_FLOOR
Can't see what's underneath this object.
Definition: define.h:289
SearchType::Item
@ Item
BOOK
@ BOOK
Definition: object.h:119
rawmaps
static int rawmaps
Whether to generate raw pics or instancied ones.
Definition: mapper.cpp:399
init_struct_map_in_quest_list
static void init_struct_map_in_quest_list(struct_map_in_quest_list *list)
Definition: mapper.cpp:951
struct_race_list
Collection of races.
Definition: mapper.cpp:219
struct_race
One monster race in the maps.
Definition: mapper.cpp:284
delete_map
void delete_map(mapstruct *m)
Frees the map, including the mapstruct.
Definition: map.cpp:1708
struct_race_list::allocated
size_t allocated
Allocated space.
Definition: mapper.cpp:222
struct_map_list::maps
struct struct_map_info ** maps
Definition: mapper.cpp:234
RING
@ RING
Definition: object.h:190
struct_race_list::count
size_t count
Number of races.
Definition: mapper.cpp:221
fill_json
static void fill_json(nlohmann::json &json)
Add all global variables to the data available to templates.
Definition: mapper.cpp:2433
add_map_to_region
static void add_map_to_region(struct_map_info *map, region *reg)
Links a map to a region.
Definition: mapper.cpp:1361
image.h
struct_map_info::level
int level
Definition: mapper.cpp:246
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.cpp:2085
artifact
in that case they will be relative to whatever the PWD of the crossfire server process is You probably shouldn though Notes on Specific and settings file datadir Usually usr share crossfire Contains data that the server does not need to modify while such as the etc A default install will pack the artifact
Definition: server-directories.txt:47
list_system_quests
static bool list_system_quests
Whether to show 'system' quests or not.
Definition: mapper.cpp:372
generate_pics
static int generate_pics
Whether to generate the picture or not.
Definition: mapper.cpp:360
MAP_WIDTH
#define MAP_WIDTH(m)
Map width.
Definition: map.h:76
create_map_object
static nlohmann::json create_map_object(struct_map_info *map, const std::string &key)
Return a JSON map object.
Definition: mapper.cpp:2339
struct_quest::mainmap
struct_map_info * mainmap
Map defining the quest.
Definition: mapper.cpp:941
env
static std::shared_ptr< inja::Environment > env
Rendering environment.
Definition: mapper.cpp:2224
MAX_BUF
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
S_KEY
#define S_KEY
Definition: mapper.cpp:438
sort_map_info
static int sort_map_info(const void *left, const void *right)
Sorts the struct_map_info according to the map name or the path if equal.
Definition: mapper.cpp:905
fill_reverse_maps
static void fill_reverse_maps(struct_map_list &list)
Fill the reverse_maps array with the provided list.
Definition: mapper.cpp:2378
d
How to Install a Crossfire Server on you must install a python script engine on your computer Python is the default script engine of Crossfire You can find the python engine you have only to install them The VisualC Crossfire settings are for d
Definition: INSTALL_WIN32.txt:13
is_valid_faceset
int is_valid_faceset(int fsn)
Checks specified faceset is valid.
Definition: image.cpp:117
esrv_del_item
void esrv_del_item(player *pl, object *ob)
Tells the client to delete an item.
Definition: main.cpp:387
struct_map_info::tiled_x_from
int tiled_x_from
Definition: mapper.cpp:261
pageToRender
One page to render, with its parameters.
Definition: mapper.cpp:2707
object::move_slow
MoveType move_slow
Movement types this slows down.
Definition: object.h:441
sort_slaying
static int sort_slaying(const void *left, const void *right)
Helper function to sort an array of struct_slaying_info.
Definition: mapper.cpp:2981
tiled_map_list
static struct_map_list tiled_map_list
Pseudo-maps grouping other maps.
Definition: mapper.cpp:269
add_race_to_list
static void add_race_to_list(struct_race *race, struct_race_list *list, int check)
Appends a race to a race list.
Definition: mapper.cpp:335
StringBuffer
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.cpp:25
FLAG_DAMNED
#define FLAG_DAMNED
The object is very cursed.
Definition: define.h:304
to
**Media tags please refer to the protocol file in doc Developers protocol Quick for your pleasure an example[/b][i] This is an old full of dirt and partially destroyed[hand] My dear as you two years i had to leave quickly Words have come to me of powerful magic scrolls discovered in an old temple by my uncle I have moved to study them I not forgot your knowledge in ancient languages I need your help for[print][b] Some parts of document are to damaged to be readable[/b][arcane] Arghis[color=Red] k h[color=dark slate blue] ark[color=#004000] fido[/color][hand] please come as fast as possible my friend[print][b] The bottom of letter seems deliberatly shredded What is but not limited to
Definition: media-tags.txt:30
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
check_equipment
static void check_equipment(object *item, struct_map_info *map)
Checks if item and its inventory are worthy to be listed.
Definition: mapper.cpp:631
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:707
EXIT
@ EXIT
Definition: object.h:186
path_stack
static std::vector< std::string > path_stack
Path, relative to output root, of pages being generated.
Definition: mapper.cpp:2630
merge_tiled_maps
static void merge_tiled_maps(struct_map_info *map, struct_map_info *tiled_map)
Merge two tiled maps groups.
Definition: mapper.cpp:1279
cached_pics
static int cached_pics
Non recreated pics.
Definition: mapper.cpp:378
struct_map_list::allocated
size_t allocated
Definition: mapper.cpp:236
list_map
static void list_map(const char *path)
Marks specified path as processed.
Definition: mapper.cpp:1340
struct_map_info::exits_to
struct_map_list exits_to
Definition: mapper.cpp:248
region
This is a game region.
Definition: map.h:279
struct_map_info::lore
char * lore
Definition: mapper.cpp:244
rendered_templates
static std::set< std::string > rendered_templates
List of generated files, to not generate multiple times.
Definition: mapper.cpp:2226
check_trigger
int check_trigger(object *op, object *cause)
Definition: button.cpp:518
apply_auto
int apply_auto(object *op)
Map was just loaded, handle op's initialization.
Definition: main.cpp:211
quest.h
S_DETECTOR
#define S_DETECTOR
Definition: mapper.cpp:440
struct_map_info::path
char * path
Full path of the map from the start directory.
Definition: mapper.cpp:241
struct_map_in_quest_list::count
size_t count
Definition: mapper.cpp:228
maps
this information may not reflect the current implementation This brief document is meant to describe the operation of the crossfire as well as the form of the data The metaserver listens on port for tcp and on port for udp packets The server sends updates to the metaserver via udp The metaserver only does basic checking on the data that server sends It trusts the server for the ip name it provides The metaserver does add the ip address and also tracks the idle time(time since last packet received). The client gets its information from the metaserver through connecting by means of tcp. The client should retrieve http the body s content type is text plain The current metaserver implementation is in Perl But the metaserver could be in any language perl is fast enough for the amount of data that is being exchanged The response includes zero or more server entries Each entry begins with the line START_SERVER_DATA and ends with the line END_SERVER_DATA Between these lines key value pairs("key=value") may be present. The entries are sent in arbitrary order. A client should apply some ordering when displaying the entries to the user. TODO b additional information outside BEGIN_SERVER_DATA END_SERVER_DATA maps
Definition: arch-handbook.txt:189
object::slaying
sstring slaying
Which race to do double damage to.
Definition: object.h:327
init_map_list
static void init_map_list(struct_map_list *list)
Initialises a list structure.
Definition: mapper.cpp:459
all_regions
std::vector< region * > all_regions
Definition: init.cpp:108
add_region_link
static void add_region_link(mapstruct *source, mapstruct *dest)
Creates a link between two maps if they are on different regions.
Definition: mapper.cpp:1409
clean_tmp_files
void clean_tmp_files(void)
Save unique maps and clean up temporary map files unless recycling temporary maps.
Definition: main.cpp:351
init_library
void init_library(void)
It is vital that init_library() is called by any functions using this library.
Definition: init.cpp:313
object::name
sstring name
The name of the object, obviously...
Definition: object.h:319
free_equipment
static void free_equipment(struct_equipment *equip)
Frees a struct_equipment.
Definition: mapper.cpp:499
created_pics
static int created_pics
Picture statistics.
Definition: mapper.cpp:377
size_large
#define size_large
Definition: mapper.cpp:364
add_map_to_slaying
static void add_map_to_slaying(struct_slaying_info *info, int item, struct_map_info *map)
Adds the specified map to the slaying information if not already present.
Definition: mapper.cpp:1472
struct_region_info::sum
int sum
Sum of locations, to compute name position.
Definition: mapper.cpp:408
struct_map_info::readable
npc_list * readable
Definition: mapper.cpp:257
OF_PNG
@ OF_PNG
PNG, default value.
Definition: mapper.cpp:382
IS_SHIELD
#define IS_SHIELD(op)
Definition: define.h:170
object::artifact
sstring artifact
If set, the item is the artifact with this name and the matching type.
Definition: object.h:322
struct_region_info::maps_list
struct_map_list maps_list
Maps in the region.
Definition: mapper.cpp:407
struct_map_info::processed
int processed
Definition: mapper.cpp:261
FIREWALL
@ FIREWALL
Definition: object.h:173
PLAYER_CHANGER
@ PLAYER_CHANGER
Definition: object.h:167
mapstruct
This is a game-map.
Definition: map.h:320
object::env
object * env
Pointer to the object which is the environment.
Definition: object.h:301
create_pathname
char * create_pathname(const char *name, char *buf, size_t size)
Get the full path to a map file.
Definition: map.cpp:104
FLAG_AUTO_APPLY
#define FLAG_AUTO_APPLY
Will be applied when created.
Definition: define.h:237
sstring
const typedef char * sstring
Definition: sstring.h:2
save_picture
static void save_picture(FILE *file, gdImagePtr pic)
Saves a map to a file, based on jpg/png settings.
Definition: mapper.cpp:1395
display_rendered_template
static bool display_rendered_template
Whether to display the template to be rendered or not.
Definition: mapper.cpp:373
templates_root
static std::string templates_root("templates/")
Directory to get templates from, with a leading /.
quest_definition
Definition of an in-game quest.
Definition: quest.h:37
struct_map_info::monsters
struct_race_list monsters
Definition: mapper.cpp:254
find_archetype
archetype * find_archetype(const char *name)
Definition: assets.cpp:270
elevation_info
static int ** elevation_info
All elevation spots in the "world_" maps.
Definition: mapper.cpp:427
color_blocking
static int color_blocking
Block all movement.
Definition: mapper.cpp:424
struct_map_in_quest::description
char * description
Description associated with the map for the quest.
Definition: mapper.cpp:934
get_template
static inja::Template get_template(const std::string &filename)
Definition: mapper.cpp:2419
mapstruct::in_memory
uint32_t in_memory
Combination of IN_MEMORY_xxx flags.
Definition: map.h:340
esrv_update_item
void esrv_update_item(int flags, object *pl, object *op)
Updates object *op for player *pl.
Definition: main.cpp:359
object::msg
sstring msg
If this is a book/sign/magic mouth/etc.
Definition: object.h:330
struct_map_info::tiled_maps
struct_map_list tiled_maps
Definition: mapper.cpp:252
region_count
static size_t region_count
Count of regions.
Definition: mapper.cpp:413
do_parameters
static void do_parameters(int argc, char **argv)
Handles command-line parameters.
Definition: mapper.cpp:3031
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:370
all_data
static nlohmann::json all_data
All JSON data available to templates.
Definition: mapper.cpp:2225
face_info::datalen
uint16_t datalen
Length of data.
Definition: image.h:12
add_monster
static void add_monster(object *monster, struct_map_info *map)
Adds a monster to the monster list.
Definition: mapper.cpp:677
struct_map_in_quest_list::list
struct struct_map_in_quest ** list
Definition: mapper.cpp:227
MAP_HEIGHT
#define MAP_HEIGHT(m)
Map height.
Definition: map.h:78
struct_quest::number
int number
Unique quest identifier.
Definition: mapper.cpp:940
pageToRender::template_name
std::string template_name
Template name to use.
Definition: mapper.cpp:2709
struct_map_info::cfregion
region * cfregion
Definition: mapper.cpp:245
get_ob_diff
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Returns a pointer to a static string which contains all variables which are different in the two give...
Definition: object.cpp:4971
find_player_partial_name
player * find_player_partial_name(const char *plname)
Find a player by a partial name.
Definition: player.cpp:114
sort_race
static int sort_race(const void *a, const void *b)
Sort 2 struct_race.
Definition: mapper.cpp:699
do_regions_link
static bool do_regions_link
Definition: mapper.cpp:432
arch_to_object
object * arch_to_object(archetype *at)
Creates and returns a new object which is a copy of the given archetype.
Definition: arch.cpp:227
object_give_identified_properties
void object_give_identified_properties(object *op)
Ensure op has all its "identified" properties set.
Definition: item.cpp:1363
stats
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various stats
Definition: stats.txt:2
init_race_list
static void init_race_list(struct_race_list *list)
Blanks a struct_race_list.
Definition: mapper.cpp:319
process_map
static void process_map(struct_map_info *info)
Processes a map.
Definition: mapper.cpp:1552
quests_allocated
static int quests_allocated
Allocated items in quests.
Definition: mapper.cpp:949
strcasecmp
int strcasecmp(const char *s1, const char *s2)
SearchName
static std::string SearchName[int(SearchType::Count)]
Search names for types, for the JS search engine.
Definition: mapper.cpp:305
sizes
static int sizes[]
Definition: mapper.cpp:362
reverse_regions
static std::map< region *, std::string > reverse_regions
Link between a region and its unique identifier.
Definition: mapper.cpp:2228
get_region_by_map
region * get_region_by_map(mapstruct *m)
Gets a region from a map.
Definition: region.cpp:71
S_DOOR
#define S_DOOR
Connection/slaying information.
Definition: mapper.cpp:437
object::randomitems
struct treasurelist * randomitems
Items to be generated.
Definition: object.h:395
create_tiled_map
static struct_map_info * create_tiled_map(void)
Create a new tiled map and link it to the tiled map list.
Definition: mapper.cpp:1263
world_map
static int world_map
If set, will generate a world map.
Definition: mapper.cpp:368
IS_ARMOR
#define IS_ARMOR(op)
Definition: define.h:166
templates
static std::vector< std::string > templates
List of template files to start processing from.
Definition: mapper.cpp:2748
ignore_path
static const char * ignore_path[]
Directories to ignore for map search.
Definition: mapper.cpp:2846
Account_Chars
Structure handling character information for an account.
Definition: account_char.h:27
struct_map_list::count
size_t count
Definition: mapper.cpp:235
slaying_count
static size_t slaying_count
Count of items in slaying_info.
Definition: mapper.cpp:451
add_template_to_render
void add_template_to_render(const std::string &template_name, const std::string &output_name, const std::string &param)
Push the specified template, with optional param, on the list of files to process.
Definition: mapper.cpp:2721
object_remove
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to.
Definition: object.cpp:1818
remove_trailing_slash
static const char * remove_trailing_slash(const char *path)
Definition: mapper.cpp:2328
a
Magical Runes Runes are magical inscriptions on the dungeon which cast a spell or detonate when something steps on them Flying objects don t detonate runes Beware ! Runes are invisible most of the time They are only visible occasionally ! There are several runes which are there are some special runes which may only be called with the invoke and people may apply it to read it Maybe useful for mazes ! This rune will not nor is it ordinarily invisible Partial Visibility of they ll be visible only part of the time They have a(your level/2) chance of being visible in any given round
infomap
static gdImagePtr infomap
World map with exits / roads / blocking / ...
Definition: mapper.cpp:420
sort_struct_map_in_quest
static int sort_struct_map_in_quest(const void *left, const void *right)
Sorts 2 struct_map_in_quest, on the map's name or path.
Definition: mapper.cpp:1038
struct_map_info::height
int height
Definition: mapper.cpp:260
ALTAR
@ ALTAR
Definition: object.h:127
player_get_delayed_buffer
SockList * player_get_delayed_buffer(player *pl)
Get a delayed socket buffer, that will be sent after the player's tick is complete.
Definition: player.cpp:4507
struct_npc_info::x
int x
Definition: mapper.cpp:212
relative_path
static void relative_path(const char *from, const char *to, char *result)
Computes the shortest path from one file to another.
Definition: mapper.cpp:836
dump_unused_maps
static void dump_unused_maps(void)
Writes the list of unused maps, maps found in the directories but not linked from the other maps.
Definition: mapper.cpp:2911
sort_region
static int sort_region(const void *left, const void *right)
Sorts an array of struct_region_info by region name.
Definition: mapper.cpp:921
special_equipment
static std::vector< struct_equipment * > special_equipment
Special equipment list.
Definition: mapper.cpp:280
make_path_to_file
void make_path_to_file(const char *filename)
Checks if any directories in the given path doesn't exist, and creates if necessary.
Definition: porting.cpp:164
fix_exits_for_map
static void fix_exits_for_map(struct_map_info *current, struct_map_list *from, int is_from)
Changes for the list all maps to the tiled map they are part of, if applicable.
Definition: mapper.cpp:1985
account_char_load
Account_Chars * account_char_load(const char *account_name)
For a given account name, load the character information and return it.
Definition: account_char.cpp:135
IS_ARROW
#define IS_ARROW(op)
Definition: define.h:178
SCROLL
@ SCROLL
Definition: object.h:226
archetype::name
sstring name
More definite name, like "generate_kobold".
Definition: object.h:484
struct_npc_info::name
const char * name
NPC's name.
Definition: mapper.cpp:210
object::nrof
uint32_t nrof
Number of objects.
Definition: object.h:342
split
static std::vector< std::string > split(const std::string &field, const std::string &by)
Definition: mapper.cpp:2736
mapstruct::reset_time
uint32_t reset_time
Server time when map gets reset, seconds since epoch.
Definition: map.h:327
do_help
static void do_help(const char *program)
Prints usage information, and exit.
Definition: mapper.cpp:2994
object::stats
living stats
Str, Con, Dex, etc.
Definition: object.h:378
list
How to Install a Crossfire Server on you must install a python script engine on your computer Python is the default script engine of Crossfire You can find the python engine you have only to install them The VisualC Crossfire settings are for but you habe then to change the pathes in the VC settings Go in Settings C and Settings Link and change the optional include and libs path to the new python installation path o except the maps ! You must download a map package and install them the share folder Its must look like doubleclick on crossfire32 dsw There are projects in your libcross lib and plugin_python You need to compile all Easiest way is to select the plugin_python ReleaseLog as active this will compile all others too Then in Visual C press< F7 > to compile If you don t have an appropriate compiler you can try to get the the VC copies the crossfire32 exe in the crossfire folder and the plugin_python dll in the crossfire share plugins folder we will remove it when we get time for it o Last showing lots of weird write to the Crossfire mailing list
Definition: INSTALL_WIN32.txt:50
artifact
This is one artifact, ie one special item.
Definition: artifact.h:14
struct_quest::name
char * name
Quest's name.
Definition: mapper.cpp:938
FLAG_IDENTIFIED
#define FLAG_IDENTIFIED
Item is identifiable (e.g.
Definition: define.h:248
get_faces_count
size_t get_faces_count()
Definition: assets.cpp:297
calc_item_power
int calc_item_power(const object *op)
This takes an object 'op' and figures out what its item_power rating should be.
Definition: item.cpp:318
write_world_info
static void write_world_info(void)
Writes the exit information world map.
Definition: mapper.cpp:2929
struct_map_in_quest_list::allocated
size_t allocated
Definition: mapper.cpp:229
tiled_map_need_pic
static int tiled_map_need_pic(struct_map_info *map)
Definition: mapper.cpp:2059
face_sets
Information about one face set.
Definition: image.h:17
SearchType::Count
@ Count
SPELL
@ SPELL
Definition: object.h:219
map_limit
static int map_limit
Maximum number of maps to browse, -1 for all.
Definition: mapper.cpp:366
closedir
int closedir(DIR *)
quests
static struct_quest ** quests
All quests in the game.
Definition: mapper.cpp:945
account_char_save
void account_char_save(Account_Chars *chars)
Saves the character information for the given account.
Definition: account_char.cpp:158
fix_tiled_map
static void fix_tiled_map(void)
Ensures all tiled maps have a name, a region, a filename and a path.
Definition: mapper.cpp:1916
output_format_type
output_format_type
Map output formats.
Definition: mapper.cpp:381
TELEPORTER
@ TELEPORTER
Definition: object.h:146
pics_allocated
static int pics_allocated
Number of created pictures for GD.
Definition: mapper.cpp:357
struct_equipment
One special item (weapon, shield, ...).
Definition: mapper.cpp:272
face_sets::faces
face_info * faces
images in this faceset
Definition: image.h:26
SockList
Contains the base information we use to make up a packet we want to send.
Definition: newclient.h:685
SPELLBOOK
@ SPELLBOOK
Definition: object.h:208
object::move_block
MoveType move_block
What movement types this blocks.
Definition: object.h:437
found_maps
static std::vector< char * > found_maps
Maps found in directories.
Definition: mapper.cpp:417
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:654
living::hp
int16_t hp
Hit Points.
Definition: living.h:40
create_treasure
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
This calls the appropriate treasure creation function.
Definition: treasure.cpp:287
find_map_by_key
static struct_map_info * find_map_by_key(const std::string &key)
Get the map with the specified key, nullptr if not found.
Definition: mapper.cpp:2235
warn_no_path
static int warn_no_path
Whether to warn of exits without a path.
Definition: mapper.cpp:402
find_quest_info
static struct_quest * find_quest_info(const char *name)
Gets the information for a quest if it exists.
Definition: mapper.cpp:970
DETECTOR
@ DETECTOR
peterm: detector is an object which notices the presense of another object and is triggered like butt...
Definition: object.h:154
find_maps
static void find_maps(const char *from)
Recursively find all all maps in a directory.
Definition: mapper.cpp:2871
struct_slaying_info::slaying
char * slaying
Slaying value.
Definition: mapper.cpp:446
is_road
static int is_road(object *item)
Checks if object is considered a road or not.
Definition: mapper.cpp:712
elevation_min
static int elevation_min
Maximal elevation found.
Definition: mapper.cpp:428
color_linked_exit
static int color_linked_exit
Exit leading to another map.
Definition: mapper.cpp:422
sort_equipment
static bool sort_equipment(const struct_equipment *l, const struct_equipment *r)
Sort 2 struct_equipment.
Definition: mapper.cpp:513
add_one_item
static void add_one_item(object *item, struct_map_info *map)
Adds an item to the list of special items.
Definition: mapper.cpp:557
account_logout
void account_logout(const char *account_name)
Remove 'account_name' from the list of logged in accounts.
Definition: account.cpp:337
SearchType::Map
@ Map
pageToRender::output_name
std::string output_name
Output file name.
Definition: mapper.cpp:2710
identify
object * identify(object *op)
Identifies an item.
Definition: item.cpp:1444