Go to the documentation of this file.
156 #include <sys/stat.h>
157 #include <sys/types.h>
289 for (test = 0; test <
list->count; test++) {
290 if (
list->races[test] == race)
295 if (
list->allocated ==
list->count) {
296 list->allocated += 50;
312 static int sizes[] = {32, 16, 8, 4, 2};
314 #define size_large sizes[0]
315 #define size_small sizes[1]
388 #define S_CONTAINER 2
417 if (
item->name ==
item->arch->clone.name &&
item->title ==
item->arch->clone.title)
466 if (
l->power !=
r->power)
467 return l->power <
r->power;
468 if (
l->calc_power !=
r->calc_power)
469 return l->calc_power <
r->calc_power;
485 [&] (
const auto *e) { return !sort_equipment(e, item) && !sort_equipment(item, e); });
517 namepl =
item->name_pl;
520 if (
item->artifact != NULL) {
556 item->name_pl = namepl;
559 if (add->
diff == NULL || strcmp(add->
diff,
"") == 0) {
664 const char *roads[] = {
670 const char *partial[] = {
674 for (test = 0; partial[test] != NULL; test++) {
675 if (strstr(
item->arch->name, partial[test]) != NULL)
682 for (test = 0; roads[test] != NULL; test++) {
683 if (strcmp(
item->arch->name, roads[test]) == 0)
713 return gdImageColorResolve(elevationmap, 200*elevation/
elevation_max, 0, 0);
715 return gdImageColorResolve(elevationmap, 0, 0, 200*elevation/
elevation_min);
731 if (sscanf(
map->path,
"/world/world_%d_%d", &
x, &
y) != 2)
746 int32_t elevation = atoi(selevation);
791 fslash = strchr(from+1,
'/');
797 rslash = strchr(
to+1,
'/');
798 while (fslash && rslash && (fslash-from == rslash-
to) && strncmp(from,
to, fslash-from+1) == 0) {
801 fslash = strchr(fslash+1,
'/');
802 rslash = strchr(rslash+1,
'/');
807 fslash = strchr(fslash+1,
'/');
907 if (
list->count ==
list->allocated) {
908 list->allocated += 10;
1035 printf(
"warning, multiple quest definition for %s, found in %s and %s.\n",
quest->name,
quest->mainmap ?
quest->mainmap->path :
"(unknown map)", mainmap->
path);
1039 while (strlen(
quest->description) &&
quest->description[strlen(
quest->description)-1] ==
'\n')
1040 quest->description[strlen(
quest->description)-1] =
'\0';
1041 quest->mainmap = mainmap;
1051 char *start, *end, *
next;
1055 start = strstr(
map->lore,
"@def");
1059 end = strstr(start,
"\n");
1061 strncpy(
name, start+5, end-start-5);
1062 name[end-start-5] =
'\0';
1064 end = strstr(
next,
"@end");
1069 memmove(start, end+4, strlen(
map->lore)-(end-start+3));
1078 strcpy(
name, start);
1084 start = end ? strstr(end,
"@def") : NULL;
1087 start = strstr(
map->lore,
"@quest");
1091 end = strstr(start,
"\n");
1093 strncpy(
name, start+7, end-start-7);
1094 name[end-start-7] =
'\0';
1096 end = strstr(
next,
"@end");
1101 memmove(start, end+4, strlen(
map->lore)-(end-start+3));
1110 strcpy(
name, start);
1116 start = end ? strstr(end,
"@quest") : NULL;
1138 info->
name = strdup(
npc->name);
1176 if (
list->count ==
list->allocated) {
1177 list->allocated += 50;
1236 add_map(change, &
map->tiled_group->tiled_maps);
1249 printf(
"tiled_map not in tiled_map_list!");
1273 tmp = strrchr((
char *)
path,
'/');
1291 if (strcmp(
path, *
map) == 0) {
1297 printf(
"Map processed but not found in directory reading? %s\n",
path);
1315 if (
regions[test]->reg == reg)
1328 if (sscanf(
map->path,
"/world/world_%d_%d", &
x, &
y) == 2) {
1346 gdImagePng(pic,
file);
1401 add->
slaying = strdup(slaying);
1478 FILE *
out = fopen(picpath,
"wb+");
1482 for (
size_t i = 1; i <
num_sizes; i++) {
1484 gdImagePtr small = gdImageCreateTrueColor(width*
sizes[i], height*
sizes[i]);
1486 out = fopen(picpath,
"wb+");
1489 gdImageDestroy(small);
1504 gdImagePtr pic =
nullptr;
1506 struct stat statspic;
1507 char exit_path[500];
1517 printf(
" processing map %s\n", info->
path);
1521 printf(
"couldn't load map %s\n", info->
path);
1530 info->
level =
m->difficulty;
1532 info->
lore = strdup(
m->maplore);
1535 if (
m->reset_group) {
1540 isworld = (sscanf(info->
path,
"/world/world_%d_%d", &
x, &
y) == 2);
1543 info->
name = strdup(
m->name);
1558 stat(tmppath, &
stats);
1559 if (stat(picpath[0], &statspic) || (statspic.st_mtime <
stats.st_mtime))
1572 for (
x = 0;
x < 4;
x++)
1573 if (
m->tile_path[
x] != NULL) {
1576 if (stat(tmppath, &
stats)) {
1577 printf(
" map %s doesn't exist in map %s, for tile %d.\n", exit_path, info->
path,
x);
1588 if (link && link !=
m) {
1633 if (!
item->slaying) {
1636 printf(
" exit without any path at %d, %d on %s\n",
item->x,
item->y, info->
path);
1639 if (strcmp(
item->slaying,
"/!"))
1643 printf(
" random map without message in %s at %d, %d\n", info->
path,
item->x,
item->y);
1646 start = strstr(
item->msg,
"\nfinal_map ");
1647 if (!start && strncmp(
item->msg,
"final_map", strlen(
"final_map")) == 0)
1651 char *end = strchr((
char *)start+1,
'\n');
1653 start += strlen(
"final_map")+2;
1654 strncpy(ep, start, end-start);
1662 if (stat(tmppath, &
stats)) {
1663 printf(
" map %s doesn't exist in map %s, at %d, %d.\n", ep, info->
path,
item->x,
item->y);
1672 if (link && link !=
m) {
1702 if (
item->invisible)
1720 if (
gdfaces[
item->face->number] != NULL && ((!
item->head && !
item->more) || (
item->arch->clone.x+hx == 0 &&
item->arch->clone.y+hy == 0))) {
1729 gdImageDestroy(pic);
1747 char mapleft[10], maptop[10], mapright[10], mapbottom[10], mappath[5000];
1757 printf(
"Generating world map in world.html...");
1760 pic = gdImageCreateTrueColor(
SIZE*30,
SIZE*30);
1763 strcat(
file,
"/world.html");
1768 for (
y = 0;
y < 30;
y++) {
1769 for (
x = 0;
x < 30;
x++) {
1770 snprintf(
name,
sizeof(
name),
"world_%d_%d", wx, wy);
1771 snprintf(mapleft,
sizeof(mapleft),
"%d",
SIZE*
x);
1772 snprintf(maptop,
sizeof(maptop),
"%d",
SIZE*
y);
1773 snprintf(mapright,
sizeof(mapright),
"%d",
SIZE*(
x+1)-1);
1774 snprintf(mapbottom,
sizeof(mapbottom),
"%d",
SIZE*(
y+1)-1);
1778 out = fopen(mappath,
"rb");
1780 printf(
"\n warning: large pic not found for world_%d_%d", wx, wy);
1785 small = gdImageCreateFromPng(
out);
1787 small = gdImageCreateFromJpeg(
out);
1790 printf(
"\n warning: pic not found for world_%d_%d", wx, wy);
1794 gdImageCopyResized(pic, small,
SIZE*
x,
SIZE*
y, 0, 0,
SIZE,
SIZE, small->sx, small->sy);
1795 gdImageDestroy(small);
1804 out = fopen(mappath,
"wb+");
1809 small = gdImageCreateTrueColor(
SIZE*30,
SIZE*30);
1810 font = gdFontGetGiant();
1811 color = gdImageColorAllocateAlpha(pic, 255, 0, 0, 20);
1828 out = fopen(mappath,
"wb+");
1831 gdImageDestroy(small);
1834 out = fopen(mappath,
"wb+");
1837 gdImageDestroy(pic);
1849 printf(
"map without path!\n");
1870 printf(
"empty tiled map group!");
1874 snprintf(
name,
sizeof(
name),
"tiled_map_group_%zu",
map);
1888 printf(
"*** warning: tiled maps %s and %s not in same region (%s and %s).\n",
1911 slash = strrchr(
name,
'/');
1982 for (
size_t race = 0; race <
races.
count; race++) {
2010 for (
size_t size = 0; size <
num_sizes; size++) {
2012 if (stat(picpath, &
stats))
2016 for (test = 0; test <
map->tiled_maps.count; test++) {
2017 if (
map->tiled_maps.maps[test]->pic_was_done)
2036 int xmin = 0, xmax = 0, ymin = 0, ymax = 0,
count, last;
2039 gdImagePtr large, load;
2046 printf(
" Generating composite map for %s...",
map->name);
2050 printf(
" already uptodate.\n");
2056 printf(
"Tiled map without tiled maps?\n");
2059 map->tiled_maps.maps[0]->processed = 1;
2060 map->tiled_maps.maps[0]->tiled_x_from = 0;
2061 map->tiled_maps.maps[0]->tiled_y_from = 0;
2066 for (tiled = 0; tiled <
map->tiled_maps.count; tiled++) {
2073 if ((
current->tiles[0]) && (
current->tiles[0]->processed == 0)) {
2074 current->tiles[0]->processed = 1;
2078 if ((
current->tiles[1]) && (
current->tiles[1]->processed == 0)) {
2079 current->tiles[1]->processed = 1;
2083 if ((
current->tiles[2]) && (
current->tiles[2]->processed == 0)) {
2084 current->tiles[2]->processed = 1;
2088 if ((
current->tiles[3]) && (
current->tiles[3]->processed == 0)) {
2089 current->tiles[3]->processed = 1;
2095 if (last ==
count) {
2096 printf(
"do_tiled_map_picture: didn't process any map in %s (%d left)??\n",
map->path, last);
2101 for (tiled = 0; tiled <
map->tiled_maps.count; tiled++) {
2102 if (
map->tiled_maps.maps[tiled]->tiled_x_from < xmin)
2103 xmin =
map->tiled_maps.maps[tiled]->tiled_x_from;
2104 if (
map->tiled_maps.maps[tiled]->tiled_y_from < ymin)
2105 ymin =
map->tiled_maps.maps[tiled]->tiled_y_from;
2106 if (
map->tiled_maps.maps[tiled]->tiled_x_from+
map->tiled_maps.maps[tiled]->width > xmax)
2107 xmax =
map->tiled_maps.maps[tiled]->tiled_x_from+
map->tiled_maps.maps[tiled]->width;
2108 if (
map->tiled_maps.maps[tiled]->tiled_y_from+
map->tiled_maps.maps[tiled]->height > ymax)
2109 ymax =
map->tiled_maps.maps[tiled]->tiled_y_from+
map->tiled_maps.maps[tiled]->height;
2114 for (tiled = 0; tiled <
map->tiled_maps.count; tiled++) {
2117 out = fopen(picpath,
"rb");
2119 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);
2123 load = gdImageCreateFromPng(
out);
2125 load = gdImageCreateFromJpeg(
out);
2128 printf(
"\n do_tiled_map_picture: warning: pic not found for %s\n",
map->tiled_maps.maps[tiled]->path);
2131 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);
2132 gdImageDestroy(load);
2137 gdImageDestroy(large);
2154 printf(
"Writing tiled map information...\n");
2170 static std::shared_ptr<inja::Environment>
env;
2184 return found->first;
2196 return found->first;
2207 for (
size_t m = 0;
m <
maps.count;
m++) {
2223 for (
size_t n = 0;
n <
list.size();
n++) {
2226 {
"name",
npc->name },
2229 {
"message",
npc->message },
2242 for (
size_t n = 0;
n <
list.count;
n++) {
2243 auto race =
list.races[
n];
2245 {
"name", race->name },
2246 {
"count", race->count },
2259 for (
size_t m = 0;
m <
list.count;
m++) {
2261 if (!
q->map || !
q->description)
2265 {
"description",
q->description },
2266 {
"quest",
q->quest->name },
2267 {
"number",
q->quest->number },
2283 {
"name",
map->name },
2284 {
"path",
map->path },
2286 {
"level",
map->level },
2287 {
"reset_group",
map->reset_group ?
map->reset_group :
"" },
2288 {
"lore",
map->lore &&
map->lore[0] ?
map->lore :
"" },
2307 {
"number",
quest->number },
2309 {
"description",
quest->description ?
quest->description :
"" },
2323 if (cur->tiled_group)
2325 snprintf(
buf,
sizeof(
buf),
"map_%04lu",
map);
2367 bool need_unknown_region =
false;
2378 snprintf(
buf,
sizeof(
buf),
"reg_%04lu", reg);
2397 auto cur =
map.first;
2398 if (cur->tiled_group)
2400 if (cur->cfregion ==
nullptr)
2401 need_unknown_region =
true;
2405 if (need_unknown_region) {
2407 {
"_key",
"reg_ffff" },
2408 {
"name",
"unknown" },
2409 {
"longname",
"unknown" },
2410 {
"description",
"unknown" },
2424 json[
"items"][idx] = {
2425 {
"name", eq->name },
2426 {
"power", eq->power },
2427 {
"calc_power", eq->calc_power },
2428 {
"diff", eq->
diff },
2438 {
"name", race->name },
2439 {
"count", race->count },
2448 {
"code",
quest->quest_code },
2449 {
"title",
quest->quest_title },
2450 {
"description",
quest->quest_description ?
quest->quest_description :
"" },
2451 {
"replayable",
quest->quest_restart },
2457 std::sort(
quest->steps.begin(),
quest->steps.end(), [] (
auto left,
auto right) { return left->step < right->step; });
2458 for (
size_t s = 0; s <
quest->steps.size(); s++) {
2459 j[
"steps"].push_back({
2460 {
"description",
quest->steps[s]->step_description ?
quest->steps[s]->step_description :
"" },
2461 {
"is_completion",
quest->steps[s]->is_completion_step ? true :
false },
2467 for (
size_t m = 0;
m < qim->maps.count;
m++) {
2470 j[
"maps"].push_back({
2471 {
"description", qim->maps.list[
m]->description },
2472 {
"map",
map->second },
2484 {
"slaying", info->slaying },
2530 auto template_name =
args.at(0)->get<std::string>();
2531 auto output_name(template_name);
2532 auto param = (
args.size() > 1 ?
args.at(1)->get<std::string>() :
"");
2534 if (!
param.empty()) {
2535 output_name =
param +
"_" + output_name;
2536 if (
param.substr(0, 4) ==
"map_") {
2538 if (
map !=
nullptr) {
2539 output_name = std::string(
map->path + 1) +
".html";
2542 if (
param.substr(0, 4) ==
"reg_") {
2544 if (reg !=
nullptr) {
2545 output_name = std::string(reg->name) +
".html";
2560 auto what =
args.at(0)->get<std::string>();
2561 if (what.substr(0, 4) ==
"map_") {
2566 if (
args.size() > 1) {
2567 size =
args.at(1)->get<
int>() - 1;
2594 auto on(output_name);
2602 r.template_name = template_name;
2608 static std::vector<std::string>
split(
const std::string &field,
const std::string &by) {
2609 std::vector<std::string>
result;
2610 size_t start = 0,
found;
2611 while ((
found = field.find(by, start)) != std::string::npos) {
2612 result.push_back(field.substr(start,
found - start));
2615 result.push_back(field.substr(start));
2629 std::string
str =
args.at(0)->get<std::string>();
2630 size_t start =
args.at(1)->get<size_t>();
2631 size_t len =
args.size() > 2 ?
args.at(2)->get<
size_t>() : std::string::npos;
2632 return str.substr(start, len);
2637 int val =
args.at(0)->get<int>(), digits =
args.at(1)->get<
int>();
2638 snprintf(
buf,
sizeof(
buf),
"%0*d", digits, val);
2639 return std::string(
buf);
2642 std::string
r(
root);
2648 return std::string(rel);
2651 const auto &src =
args.at(0);
2652 auto field =
args.at(1)->get<std::string>();
2654 auto found = std::find_if(src->begin(), src->end(), [&field, &
value] (
auto item) {
2655 return item[field] == *value;
2657 if (
found == src->end()) {
2664 const auto &src =
args.at(0);
2665 auto field =
args.at(1)->get<std::string>();
2667 if (
filter->is_array()) {
2668 std::copy_if(src->begin(), src->end(), std::back_inserter(ret), [&] (
auto &
item) {
2669 auto val = item[field];
2670 return std::find_if(filter->begin(), filter->end(), [&] (auto li) { return val == li; }) !=
filter->end();
2673 std::copy_if(src->begin(), src->end(), std::back_inserter(ret), [&] (
auto &
item) {
2674 return filter->get<std::string>() == item[field];
2680 const auto &src =
args.at(0);
2681 std::vector<nlohmann::json> ret;
2682 for (
auto i : *src) {
2686 bool invert =
args.size() > 2 ?
args.at(2)->get<
bool>() :
false;
2687 bool ignore_case =
args.size() > 3 ?
args.at(3)->get<
bool>() :
true;
2688 std::sort(ret.begin(), ret.end(), [&] (
auto left,
auto right) {
2689 for (auto field : fields) {
2690 nlohmann::json l = left[field], r = right[field];
2691 if (ignore_case && l.is_string() && r.is_string()) {
2692 std::string ls(l.get<std::string>()), rs(r.get<std::string>());
2693 std::transform(ls.begin(), ls.end(), ls.begin(), [](unsigned char c){ return std::tolower(c); });
2694 std::transform(rs.begin(), rs.end(), rs.begin(), [](unsigned char c){ return std::tolower(c); });
2698 return invert ? (rs < ls) : (ls < rs);
2703 return invert ? (r < l) : (l < r);
2710 env->set_trim_blocks(
true);
2711 env->set_lstrip_blocks(
true);
2741 struct dirent *
file;
2742 struct stat statbuf;
2744 char path[1024], full[1024];
2747 for (ignore = 0;
ignore_path[ignore] != NULL; ignore++) {
2758 for (ignore = 0;
ignore_name[ignore] != NULL; ignore++) {
2765 snprintf(full,
sizeof(full),
"%s/%s",
path,
file->d_name);
2767 status = stat(full, &statbuf);
2768 snprintf(full,
sizeof(full),
"%s/%s", from,
file->d_name);
2769 if ((
status != -1) && (S_ISDIR(statbuf.st_mode))) {
2784 snprintf(
path,
sizeof(
path),
"%s/%s",
root,
"maps.unused");
2787 printf(
"Unable to open file maps.unused!\n");
2794 printf(
"%ld unused maps.\n",
found_maps.size());
2802 gdImagePtr elevationmap;
2807 printf(
"Saving exit/blocking/road information...");
2817 puts(
"Error: Could not save elevation world map due to not finding any minimum or maximum elevation.");
2821 elevationmap = gdImageCreateTrueColor(30*50, 30*50);;
2823 for (
x = 0;
x < 30*50;
x++) {
2824 for (
y = 0;
y < 30*50;
y++) {
2829 printf(
"Saving elevation world map...");
2835 gdImageDestroy(elevationmap);
2836 elevationmap = NULL;
2863 printf(
"Crossfire Mapper will generate pictures of maps, and create indexes for all maps and regions.\n\n");
2864 printf(
"Syntax: %s\n\n", program);
2865 printf(
"Optional arguments:\n");
2866 printf(
" -nopics don't generate pictures.\n");
2867 printf(
" -root=<path> destination path. Default 'html'.\n");
2868 printf(
" -limit=<number> stop processing after this number of maps, -1 to do all maps (default).\n");
2869 printf(
" -showmaps outputs the name of maps as they are processed.\n");
2870 printf(
" -jpg[=quality] generate jpg pictures, instead of default png. Quality should be 0-95, -1 for automatic.\n");
2871 printf(
" -forcepics force to regenerate pics, even if pics's date is after map's.\n");
2872 printf(
" -addmap=<map> adds a map to process. Path is relative to map's directory root.\n");
2873 printf(
" -rawmaps generates maps pics without items on random (shop, treasure) tiles.\n");
2874 printf(
" -warnnopath inform when an exit has no path set.\n");
2875 printf(
" -listunusedmaps finds all unused maps in the maps directory.\n");
2876 printf(
" -noworldmap don't write the world map in world.png.\n");
2877 printf(
" -noregionslink don't generate regions relation file.\n");
2878 printf(
" -regionslink generate regions relation file.\n");
2879 printf(
" -noexitmap don't generate map of exits.\n");
2880 printf(
" -exitmap generate map of exits.\n");
2881 printf(
" -tileset=<number> use specified tileset to generate the pictures. Default 0 (standard).\n");
2882 printf(
" -details-quests list all quests steps. Default no.\n");
2883 printf(
" -list-system-quests include 'system' quests in quest list. Default no.\n");
2884 printf(
" -templates-dir=[dir] set the directory to get templates from. Default 'templates/'.\n");
2885 printf(
" -add-template=[file] add a template to process. May be specified multiple times. If empty, 'index.html' is used.\n");
2886 printf(
" -list-template-to-process display the name of the template about to be rendered. Useful for debugging.");
2905 while (arg < argc) {
2906 if (strcmp(argv[arg],
"-nopics") == 0)
2908 else if (strncmp(argv[arg],
"-root=", 6) == 0)
2909 strncpy(
root, argv[arg]+6, 500);
2910 else if (strncmp(argv[arg],
"-limit=", 7) == 0)
2912 else if (strcmp(argv[arg],
"-showmaps") == 0)
2914 else if (strcmp(argv[arg],
"-jpg") == 0) {
2916 if (argv[arg][4] ==
'=') {
2922 else if (strcmp(argv[arg],
"-forcepics") == 0)
2924 else if (strncmp(argv[arg],
"-addmap=", 8) == 0) {
2925 if (*(argv[arg]+8) ==
'/')
2926 strncpy(
path, argv[arg]+8, 500);
2928 snprintf(
path, 500,
"/%s", argv[arg]+8);
2931 else if (strcmp(argv[arg],
"-rawmaps") == 0)
2933 else if (strcmp(argv[arg],
"-warnnopath") == 0)
2935 else if (strcmp(argv[arg],
"-listunusedmaps") == 0)
2937 else if (strcmp(argv[arg],
"-noworldmap") == 0)
2939 else if (strcmp(argv[arg],
"-noregionslink") == 0)
2941 else if (strcmp(argv[arg],
"-regionslink") == 0)
2943 else if (strcmp(argv[arg],
"-noexitmap") == 0)
2945 else if (strcmp(argv[arg],
"-exitmap") == 0)
2947 else if (strncmp(argv[arg],
"-tileset=", 9) == 0) {
2950 }
else if (strcmp(argv[arg],
"-detail-quests") == 0) {
2952 }
else if (strcmp(argv[arg],
"-list-system-quests") == 0) {
2954 }
else if (strncmp(argv[arg],
"-templates-dir=", 15) == 0) {
2956 }
else if (strncmp(argv[arg],
"-add-template=", 14) == 0) {
2958 }
else if (strcmp(argv[arg],
"-list-template-to-process") == 0) {
2965 strcpy(
root,
"html");
2984 strcpy(dummy,
root);
2985 strcat(dummy,
"/a");
2998 return (
value ?
"yes" :
"no");
3005 return find->second;
3024 printf(
"Initializing Crossfire data...\n");
3042 printf(
"\n\n done.\n\n");
3045 printf(
"Erreor: invalid tileset %d!\n",
tileset);
3059 strcpy(
max,
"(none)");
3060 printf(
"Crossfire map browser generator\n");
3061 printf(
"-------------------------------\n\n");
3062 printf(
"Parameters:\n");
3063 printf(
" path to write files: %s\n",
root);
3064 printf(
" maximum number of maps to process: %s\n",
max);
3081 printf(
" templates to process: ");
3082 const char *sep =
"";
3084 printf(
"%s%s", sep, f.c_str());
3092 printf(
"listing all maps...");
3094 printf(
"done, %ld maps found.\n",
found_maps.size());
3098 infomap = gdImageCreateTrueColor(30*50, 30*50);
3105 for (i = 0; i < 50*30; i++)
3110 printf(
"browsing maps...\n");
3120 printf(
" --- map limit reached, stopping ---\n");
3147 std::sort(
system_quests.begin(),
system_quests.end(), [] (
const auto &left,
const auto &right) { return strcmp(left->quest_code, right->quest_code) < 0; });
3154 if (!
file.empty()) {
3159 const auto fullStart =
time(
nullptr);
3160 printf(
"rendering pages...");
3165 while (!
pages.empty()) {
3166 auto p =
pages.back();
3168 if (p.param.empty())
3172 const auto start =
time(
nullptr);
3174 printf(
" rendering page %s (%s)... ", p.template_name.c_str(), p.param.c_str());
3181 const auto elapsed =
time(
nullptr) - start;
3183 printf(
"took %ld seconds\n", elapsed);
3187 const auto elapsed =
time(
nullptr) - fullStart;
3188 printf(
" done, took %ld seconds\n", elapsed);
3207 while ((invtmp->stats.hp--) > 0)
3209 invtmp->randomitems = NULL;
3213 && invtmp->type !=
SPELL
3214 && invtmp->type !=
CLASS
3220 invtmp->randomitems = NULL;
3240 tmp->randomitems = NULL;
3246 while ((
tmp->stats.hp--) > 0)
3248 tmp->randomitems = NULL;
3272 tmp->randomitems = NULL;
3285 #ifndef DOXYGEN_SHOULD_SKIP_THIS
3291 void draw_ext_info(
int,
int,
const object *, uint8_t, uint8_t,
const char *txt) {
3292 fprintf(
logfile,
"%s\n", txt);
3304 fprintf(
logfile,
"ext_info_map: %s\n", str1);
3374 while ((
op->stats.hp--) > 0)
static struct_race * get_race(const char *name)
struct struct_map_info * tiles[4]
void move_firewall(object *)
static void write_tiled_map_page(struct_map_info *map)
static void fix_tiled_map_monsters(void)
void do_auto_apply(mapstruct *m)
static void add_map(struct_map_info *info, struct_map_list *list)
#define HAS_RANDOM_ITEMS(op)
#define FREE_OBJ_NO_DESTROY_CALLBACK
static const char * ignore_name[]
static struct_quest * get_quest_info(const char *name)
static region * find_region_by_key(const std::string &key)
static void process_map_lore(struct_map_info *map)
const artifact * find_artifact(const object *op, const char *name)
region * get_region_struct(void)
static int compare_map_info(const struct_map_info *left, const struct_map_info *right)
static std::string path_from_current(const std::string &path)
void quest_for_each(quest_op op, void *user)
void LOG(LogLevel logLevel, const char *format,...)
static nlohmann::json generate_picture_link(inja::Arguments &args)
struct struct_map_info * tiled_group
static const int num_sizes
static void add_slaying(struct_map_info *map, object *item)
based on the size of the this randomly makes land number of spaces randomly lower or higher The default is Note that this is run also based on the the altitude amount will likely be less So if you do something like l and n
mapstruct * ready_map_name(const char *name, int flags)
static void write_tiled_maps(void)
char first_map_path[MAX_BUF]
#define QUERY_FLAG(xyz, p)
struct_map_in_quest_list maps
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
static nlohmann::json create_quest_object(struct_quest *quest, const std::string &key)
static struct_map_info * create_map_info(void)
basic_json<> json
default JSON class
void esrv_del_item(player *, object *)
static void write_pictures_from_real_size(const char *path, gdImagePtr real, int width, int height)
static std::map< region *, std::set< region * > > region_links
int get_face_fallback(int faceset, uint16_t imageno)
static event_registration c
static enum output_format_type output_format
StringBuffer * stringbuffer_new(void)
static nlohmann::json create_npc_array(npc_list &list)
static struct_map_info * get_map_info(const char *path)
static void fix_exits_to_tiled_maps(void)
static std::map< struct_map_info *, std::string > reverse_maps
static size_t slaying_allocated
void give_artifact_abilities(object *op, const object *artifact)
static struct_equipment * get_equipment(void)
static int is_special_equipment(object *item)
static size_t region_allocated
static nlohmann::json generate_page_and_link(inja::Arguments &args)
non standard information is not specified or uptime fields
face_sets * find_faceset(int id)
static nlohmann::json create_map_in_quest_array(struct_map_in_quest_list &list)
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
static const char * yesno(int value)
static void fix_map_names(void)
struct_map_list maps[S_MAX]
static struct_map_list maps_list
static int color_unlinked_exit
static std::vector< pageToRender > pages
static int list_unused_maps
void draw_ext_info_format(int, int, const object *, uint8_t, uint8_t, const char *format,...)
void esrv_send_item(object *, object *)
void push_back(basic_json &&val)
add an object to an array
static int dump(const std::set< std::string > &items, const char *name)
static nlohmann::json create_region_array(const std::set< region * > ®ions)
void clean_tmp_files(void)
static void add_npc_to_map(npc_list *list, const object *npc)
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
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
Almost all the spell_ *base png files are taken from JXClient s source
const char * object_get_value(const object *op, const char *const key)
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
object * object_insert_in_ob(object *op, object *where)
void apply_auto_fix(mapstruct *)
void account_char_save(Account_Chars *)
Plugin animator file specs[Config] name
std::string template_name
static int world_exit_info
static int sort_struct_quest(const void *left, const void *right)
struct struct_quest * quest
#define FLAG_IS_A_TEMPLATE
static void init_renderer_env()
static event_registration m
char * stringbuffer_finish(StringBuffer *sb)
void object_free_drop_inventory(object *ob)
DIR * opendir(const char *)
static inja::TemplateStorage templateCache
static struct struct_region_info ** regions
struct_map_list exits_from
static bool detail_quests
static struct_equipment * ensure_unique(struct_equipment *item)
static struct_slaying_info * get_slaying_struct(const char *slaying)
static void generate_picture_path(const char *path, size_t pic_size, char *out, size_t len)
void set_darkness_map(mapstruct *)
static void define_quest(const char *name, struct_map_info *mainmap, const char *description)
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
static void add_to_struct_map_in_quest_list(struct_map_in_quest_list *list, struct_map_in_quest *item)
static void do_tiled_map_picture(struct_map_info *map)
static struct_slaying_info ** slaying_info
sstring add_string(const char *str)
static struct_race_list races
std::vector< struct_npc_info * > npc_list
void object_get_multi_size(const object *ob, int *sx, int *sy, int *hx, int *hy)
int main(int argc, char **argv)
static const char * output_extensions[]
static nlohmann::json create_maps_array(struct_map_list &maps)
static std::vector< quest_definition * > system_quests
static int get_elevation_color(int elevation, gdImagePtr elevationmap)
static std::set< std::string > reset_groups
static void quest_callback(const quest_definition *quest, void *)
struct dirent * readdir(DIR *)
static int is_slaying(object *item)
static nlohmann::json create_race_array(struct_race_list &list)
Account_Chars * account_char_load(const char *)
void dragon_ability_gain(object *, int, int)
spell prayer lvl t sp speed range duration short description
array_t * array
array (stored with pointer to save storage)
void object_update_speed(object *op)
struct_map_in_quest_list quests
static void write_world_map(void)
static void add_map_to_quest(struct_map_info *map, const char *name, const char *description)
static struct_npc_info * create_npc_info(const object *npc)
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
void esrv_update_item(int, object *, object *)
void object_free(object *ob, int flags)
static int is_blocking(object *item)
static void do_exit_map(mapstruct *map)
static void create_destination(void)
struct struct_race ** races
#define FLAG_UNAGGRESSIVE
static void check_slaying_inventory(struct_map_info *map, object *item)
static void append_map_list(struct_map_list &dest, struct_map_list &src)
static void init_struct_map_in_quest_list(struct_map_in_quest_list *list)
void delete_map(mapstruct *m)
struct struct_map_info ** maps
static void fill_json(nlohmann::json &json)
static void add_map_to_region(struct_map_info *map, region *reg)
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
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
static bool list_system_quests
static nlohmann::json create_map_object(struct_map_info *map, const std::string &key)
struct_map_info * mainmap
static std::shared_ptr< inja::Environment > env
static int sort_map_info(const void *left, const void *right)
static void fill_reverse_maps(struct_map_list &list)
int is_valid_faceset(int fsn)
pluglist shows those as well as a short text describing each the list will simply appear empty The keyword for the Python plugin is Python plugout< keyword > Unloads a given identified by its _keyword_ So if you want to unload the Python you need to do plugout Python plugin< libname > Loads a given whose _filename_ is libname So in the case of you d have to do a plugin cfpython so Note that all filenames are relative to the default plugin path(SHARE/plugins). Console messages. ----------------- When Crossfire starts
static int sort_slaying(const void *left, const void *right)
static struct_map_list tiled_map_list
static void add_race_to_list(struct_race *race, struct_race_list *list, int check)
static void check_equipment(object *item, struct_map_info *map)
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
static std::vector< std::string > path_stack
static void merge_tiled_maps(struct_map_info *map, struct_map_info *tiled_map)
static void list_map(const char *path)
static std::set< std::string > rendered_templates
int apply_auto(object *op)
static void init_map_list(struct_map_list *list)
std::vector< region * > all_regions
static void add_region_link(mapstruct *source, mapstruct *dest)
static void free_equipment(struct_equipment *equip)
void esrv_update_spells(player *)
static void add_map_to_slaying(struct_slaying_info *info, int item, struct_map_info *map)
std::map< std::string, Template > TemplateStorage
void account_char_free(Account_Chars *)
struct_map_list maps_list
std::vector< const json * > Arguments
char * create_pathname(const char *name, char *buf, size_t size)
const typedef char * sstring
a class to store JSON values
static void save_picture(FILE *file, gdImagePtr pic)
static bool display_rendered_template
static std::string templates_root("templates/")
struct_race_list monsters
archetype * find_archetype(const char *name)
static int ** elevation_info
static int color_blocking
Python Guilds Quick outline Add a guild(mapmakers) this is still a problem *after dropping the token to gain access to the stove a woodfloor now appears which is Toolshed Token(found in Guild_HQ) *Note also have multiple gates in place to protect players and items from the mana explosion drop x for Jewelers room *Jewelers room works just need to determine what x is drop x for Thaumaturgy room *Thaumaturgy room works just need to determine what x is drop gold dropping the Firestar named fearless allows access to but I suspect that the drop location of the chest is not as intended because the player is in the way once you enter the chest the exit back to the basement is things such as the message et al reside on teleporters which then transport items to the map as they are when the map is already purchased items reappear in that area From my this does not cause any problems at the moment But this should be corrected fixed Major it s now possible to buy guilds Ryo Update Uploaded guild package to CVS Changes the cauldrons and the charging room I spent a while agonizing over They were natural guild enhancements but much too much value for any reasonable expense to buy them Then I thought that they should be pay access but at a greatly reduced rate SO when you buy a forge or whatever for your guild it is available on a perplayer daily rate but it will be accessable for testing and to DMs to play with Like I said lots still to do with the especially comingt up with quest items for buying things like the new workshops and stuff One of the things I would like some input on would be proposals for additional fields for either the guildhouses or guild datafiles to play with Currently the Guildhouse but there is no reason we can t have more than one measure of a guild perhaps have dues relate to Dues and use points for some other suspended or inactive or when a guild is founded inactive active Guilds have the format
static inja::Template get_template(const std::string &filename)
struct_map_list tiled_maps
Install Bug reporting Credits but rather whatever guild name you are using *With the current map and server there are three they and GreenGoblin *Whatever name you give the folder should but it will still use GUILD_TEMPLATE *You can change what guild it uses by editing the map files Modify Map or objects if you want to use the optional Python based Guild Storage hall The first three are on the main the next two are in the guild_hq and the final one is in hallofjoining Withe the Storage three objects are found on the main floor and the last two are in the basement It s not that but you will need a map editor You find the object that has the click edit and change the line script options(which currently is "GUILD_TEMPALTE") to the guild you wish to use. And make sure you use the same one for all of them or it won 't work. Here 's a quick HOWTO for using the map editor to make these changes edit the mainfloor map exit(x15, y29 - set to/Edit/This/Exit/Path in the template) back to the world map as well. If you are using the Storage Hall map(storage_hall)
void ext_info_map(int, const mapstruct *, uint8_t, uint8_t, const char *str1)
static size_t region_count
void command_help(object *, const char *)
static void do_parameters(int argc, char **argv)
#define CLEAR_FLAG(xyz, p)
static nlohmann::json all_data
static void add_monster(object *monster, struct_map_info *map)
struct struct_map_in_quest ** list
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
static int sort_race(const void *a, const void *b)
static bool do_regions_link
object * arch_to_object(archetype *at)
void object_give_identified_properties(object *op)
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various stats
static void init_race_list(struct_race_list *list)
static void process_map(struct_map_info *info)
static int quests_allocated
int strcasecmp(const char *s1, const char *s2)
object * find_skill_by_number(object *, int)
void account_logout(const char *)
static std::map< region *, std::string > reverse_regions
region * get_region_by_map(mapstruct *m)
static struct_map_info * create_tiled_map(void)
static std::vector< std::string > templates
static const char * ignore_path[]
static size_t slaying_count
SockList * player_get_delayed_buffer(player *)
void add_template_to_render(const std::string &template_name, const std::string &output_name, const std::string ¶m)
void object_remove(object *op)
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
static gdImagePtr infomap
static int sort_struct_map_in_quest(const void *left, const void *right)
static void relative_path(const char *from, const char *to, char *result)
static void dump_unused_maps(void)
void rod_adjust(object *)
static int sort_region(const void *left, const void *right)
static std::vector< struct_equipment * > special_equipment
object * generate_treasure(treasurelist *t, int difficulty)
void make_path_to_file(const char *filename)
#define FREE_OBJ_FREE_INVENTORY
static void fix_exits_for_map(struct_map_info *current, struct_map_list *from, int is_from)
void draw_ext_info(int, int, const object *, uint8_t, uint8_t, const char *txt)
static std::vector< std::string > split(const std::string &field, const std::string &by)
No space after the left no space before the right paren Comma right after the formal param
static void do_help(const char *program)
IteratorType erase(IteratorType pos)
remove element given an iterator
int calc_item_power(const object *op)
static void write_world_info(void)
static int tiled_map_need_pic(struct_map_info *map)
static struct_quest ** quests
static void fix_tiled_map(void)
static gdImagePtr * gdfaces
static int pics_allocated
static std::vector< char * > found_maps
#define FOR_INV_PREPARE(op_, it_)
player * find_player_partial_name(const char *)
static struct_map_info * find_map_by_key(const std::string &key)
static struct_quest * find_quest_info(const char *name)
static void find_maps(const char *from)
static int is_road(object *item)
static int color_linked_exit
static bool sort_equipment(const struct_equipment *l, const struct_equipment *r)
static void add_one_item(object *item, struct_map_info *map)
object * identify(object *op)