 |
Crossfire Server, Trunk
1.75.0
|
Go to the documentation of this file.
34 #define POLAR_BASE_TEMP 0
35 #define EQUATOR_BASE_TEMP 30
36 #define SEASONAL_ADJUST 10
37 #define GULF_STREAM_WIDTH 3
38 #define GULF_STREAM_BASE_SPEED 40
41 #define PRESSURE_ITERATIONS 30
42 #define PRESSURE_AREA 180
43 #define PRESSURE_ROUNDING_FACTOR 2
44 #define PRESSURE_ROUNDING_ITER 1
45 #define PRESSURE_SPIKES 3
46 #define PRESSURE_MAX 1040
47 #define PRESSURE_MIN 960
51 #define SKY_LIGHTCLOUD 1
52 #define SKY_OVERCAST 2
53 #define SKY_LIGHT_RAIN 3
55 #define SKY_HEAVY_RAIN 5
56 #define SKY_HURRICANE 6
61 #define SKY_LIGHT_SNOW 13
63 #define SKY_HEAVY_SNOW 15
64 #define SKY_BLIZZARD 16
73 #define WIND_FACTOR 4.0
76 #define WEATHERMAPTILESX 100
77 #define WEATHERMAPTILESY 100
214 .worldmaptilesizey = 50,
228 {
"mint",
"grass", 10, 1.0, 2.0, 30, 100, 10, 25, -100, 9999, 2},
229 {
"rose_red",
"grass", 15, 1.0, 2.0, 30, 100, 10, 25, -100, 9999, 2},
230 {
"rose_red",
"hills", 15, 1.0, 2.0, 30, 100, 10, 25, -100, 9999, 2},
235 {
"mint",
"brush", 8, 1.0, 2.0, 30, 100, 10, 25, -100, 9999, 2},
236 {
"blackroot",
"swamp", 15, 1.6, 2.0, 60, 100, 20, 30, -100, 1500, 0},
237 {
"mushroom_1",
"grass", 15, 1.6, 2.0, 60, 100, 3, 30, -100, 1500, 0},
238 {
"mushroom_2",
"grass", 15, 1.6, 2.0, 60, 100, 3, 30, -100, 1500, 0},
239 {
"mushroom_1",
"swamp", 15, 1.6, 2.0, 60, 100, 3, 30, -100, 1500, 0},
240 {
"mushroom_2",
"swamp", 15, 1.6, 2.0, 60, 100, 3, 30, -100, 1500, 0},
241 {
"mushroom_1",
"hills", 15, 1.6, 2.0, 60, 100, 3, 30, -100, 1500, 0},
242 {
"mushroom_2",
"hills", 15, 1.6, 2.0, 60, 100, 3, 30, -100, 1500, 0},
243 {
"pipeweed",
"farmland", 20, 1.0, 2.0, 30, 100, 10, 25, 100, 5000, 0},
244 {
"cabbage",
"farmland", 10, 1.0, 2.0, 30, 100, 10, 25, -100, 9999, 0},
245 {
"onion",
"farmland", 10, 1.0, 2.0, 30, 100, 10, 25, 100, 9999, 0},
246 {
"carrot",
"farmland", 10, 1.0, 2.0, 30, 100, 10, 25, 100, 9999, 0},
247 {
"thorns",
"brush", 15, 0.5, 1.3, 30, 100, 10, 25, -100, 9999, 0},
248 {
"mountain_foilage",
"mountain", 6, 1.0, 2.0, 25, 100, 5, 30, 0, 15999, 2},
249 {NULL, NULL, 1, 0.0, 0.0, 0, 0, 0, 0, 0, 0, 0}
259 {
"dunes", NULL, 2, 0.0, 0.03, 0, 20, 10, 99, 0, 4000, 0},
260 {
"desert", NULL, 1, 0.0, 0.05, 0, 20, 10, 99, 0, 4000, 0},
261 {
"pstone_2", NULL, 1, 0.0, 0.05, 0, 20, -30, 10, 0, 4000, 0},
262 {
"pstone_3", NULL, 1, 0.0, 0.05, 0, 20, -30, 10, 0, 4000, 0},
263 {
"grassbrown", NULL, 1, 0.05, 1.0, 20, 80, -20, -3, 0, 5000, 0},
264 {
"grass_br_gr", NULL, 1, 0.05, 1.0, 20, 80, -3, 5, 0, 5000, 0},
265 {
"grass", NULL, 1, 0.05, 1.0, 20, 80, 5, 15, 0, 5000, 0},
266 {
"grassmedium", NULL, 1, 0.05, 1.0, 20, 80, 15, 25, 0, 5000, 0},
267 {
"grassdark", NULL, 1, 0.05, 1.0, 20, 80, 25, 35, 0, 5000, 0},
268 {
"brush", NULL, 1, 0.2, 1.0, 25, 70, 0, 30, 500, 6000, 0},
270 {
"evergreens2",
"brush", 1, 0.5, 1.8, 30, 90, -30, 24, 3000, 8000, 0},
271 {
"fernsdense",
"brush", 1, 0.9, 2.5, 50, 100, 10, 35, 1000, 6000, 0},
272 {
"fernssparse",
"brush", 1, 0.7, 2.0, 30, 90, -15, 35, 0, 4000, 0},
273 {
"woods4",
"brush", 1, 0.1, 0.8, 30, 60, -5, 25, 1000, 4500, 0},
274 {
"woods5",
"brush", 1, 0.6, 1.5, 20, 70, -15, 20, 2000, 5500, 0},
275 {
"forestsparse",
"brush", 1, 0.3, 1.5, 15, 60, -20, 25, 0, 4500, 0},
286 {
"steppe", NULL, 1, 0.5, 1.3, 0, 30, -20, 35, 1000, 6000, 0},
287 {
"steppelight", NULL, 1, 0.0, 0.6, 0, 20, -50, 35, 0, 5000, 0},
288 {
"hills", NULL, 1, 0.1, 0.9, 20, 80, -10, 30, 5000, 8500, 0},
289 {
"hills_rocky", NULL, 1, 0.0, 0.9, 0, 100, -50, 50, 5000, 8500, 0},
290 {
"swamp", NULL, 1, 1.0, 9.9, 55, 80, 10, 50, 0, 1000, 0},
291 {
"deep_swamp", NULL, 1, 1.0, 9.9, 80, 100, 10, 50, 0, 1000, 0},
292 {
"mountain", NULL, 1, 0.0, 9.9, 0, 100, -50, 50, 8000, 10000, 0},
293 {
"mountain2", NULL, 1, 0.0, 9.9, 0, 100, -50, 50, 9500, 11000, 0},
294 {
"mountain4", NULL, 1, 0.0, 9.9, 0, 100, -50, 50, 10500, 12000, 0},
295 {
"mountain5", NULL, 1, 0.0, 9.9, 0, 100, -50, 50, 11500, 13500, 0},
296 {
"wasteland", NULL, 1, 0.0, 9.9, 0, 100, -50, 50, 13000, 99999, 0},
298 {
"palms",
"pstone_1", 1, 0.01, 0.1, 0, 30, 5, 99, 0, 4000, 0},
299 {
"large_stones", NULL, 1, 0.0, 9.9, 0, 100, -50, 50, 6000, 8000, 0},
300 {
"earth", NULL, 1, 0.0, 1.0, 0, 70, -30, 15, 0, 6000, 0},
301 {
"medium_stones", NULL, 1, 1.0, 3.0, 70, 100, -30, 10, 0, 4000, 0},
302 {
"earth", NULL, 1, 0.1, 0.9, 20, 80, -30, 30, 0, 4999, 0},
303 {
"swamp", NULL, 1, 1.0, 9.9, 50, 100, -30, 10, 0, 4000, 0},
304 {
"earth", NULL, 1, 0.0, 99.9, 0, 100, -99, 99, 0, 99999, 0},
305 {NULL, NULL, 1, 0.0, 0.0, 0, 0, 0, 0, 0, 0, 0}
361 LOG(
llevError,
"weathermap_to_worldmap_corner: Invalid direction %d given, should be in set {2,4,6,8}.\n", dir);
367 snprintf(
buffer, bufsize,
"world/world_%d_%d", nx, ny);
386 if ((x+y) > equator) {
390 }
else if ((x+y) < equator) {
464 const char *filename =
m->path;
466 while (*filename ==
'/') {
475 if (fx == -2 || fy == -2) {
482 LOG(
llevDebug,
"worldmap_to_weathermap(%s)\n", filename);
485 int amt = sscanf(filename,
"world/world_%d_%d", &fx, &fy);
537 object *tmp, *snow = NULL;
556 if (avoid && gotsnow) {
575 if (avoid && gotsnow) {
619 #define WEATHER_OVERLAY 1
620 #define WEATHER_NO_FLOOR 2
621 #define WEATHER_NO_SAVE 4
690 while (*
line ==
' ' || *
line ==
',')
725 for (tx = -1; tx < 2; tx++) {
726 for (ty = -1; ty < 2; ty++) {
727 if (!(tx == 0 && ty == 0)) {
760 for (tx = -1; tx < 2; tx++) {
761 for (ty = -1; ty < 2; ty++) {
762 if (tx != 0 && ty != 0) {
830 int x, y, l, n, j, k, is_storm;
848 is_storm = (n < 1013 &&
rndm(1, 10) == 1);
849 for (j = x-2; j < x+2; j++) {
850 for (k = y-2; k < y+2; k++) {
878 0, 0, 0, 0, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1};
935 for (i = 0; i <= tod->
hour; i++) {
971 int wx, wy, temp, eleva, elevb, trees;
1002 elevb = eleva - elevb;
1031 int dist, equator, elev, n, trees;
1045 n -= (tod->
month*tdiff);
1076 else if (trees >= 30){
1106 int calc, inv_pressure;
1120 press_root = sqrt(inv_pressure);
1121 calc =
MAX(0,
MIN((
int)(max_root*100), (
int)(press_root *
weathermap[x][y].humid)));
1126 calc /= (int)(max_root*100 / 7) + 1;
1137 if (temp > 0 && temp < 5 &&
weathermap[x][y].humid > 95 &&
1141 if (temp > 0 && temp < 5 &&
weathermap[x][y].humid > 70 &&
1164 int buffer_pressure;
1175 for (x = xy-xy_eff; x < xy_eff; ++x) {
1204 static int humid_tile(
const int x,
const int y,
const int dark) {
1206 int ox = x, oy = y, humid, evap, tempeffect;
1235 tempeffect = light*light/4;
1238 tempeffect = light*light/5;
1245 tempeffect = light*4/5;
1249 tempeffect = light/2;
1253 tempeffect = light/3;
1258 tempeffect = light/5;
1269 evap =
MAX(0, evap);
1307 int x, y, tx, diroffset,
dirdiff, ystart, ydiff, ylimup, ylimlow;
1331 for (y = ystart; y > ylimlow && y < ylimup; y += ydiff) {
1363 if (
rndm(1, 1000) == 1) {
1383 if (
rndm(1, 75) <= 2) {
1510 if (
rndm(0, 99) + pct_precip >= 100) {
1515 if (temp < -2 || (temp <= 2 &&
rndm(0, 2+temp) - 2 <= 0)) {
1526 if (tmp->
arch == at) {
1530 else if ((tmp->
arch->
name == snowc && at->
name == rain) ||
1565 int x, y, temp, sky, wx, wy;
1569 for (x = 0; x <
m->width; ++x)
1570 for (y = 0; y <
m->height; ++y) {
1587 int avoid, temp, sky, gotsnow, nodstk;
1588 object *tmp, *oldsnow, *topfloor;
1589 archetype *at, *doublestack, *doublestack2;
1596 if (
rndm(0, 2) > 0) {
1638 if (tmp->arch->name != dungmag) {
1645 if (topfloor == NULL) {
1654 if (repl->special_snow != NULL) {
1655 at = repl->special_snow;
1657 if (repl->doublestack_arch != NULL && !nodstk) {
1658 doublestack = repl->doublestack_arch;
1664 if (gotsnow && at) {
1665 if (oldsnow->
arch == at) {
1672 doublestack2 = NULL;
1675 if (repl->doublestack_arch == NULL) {
1680 doublestack2 = repl->doublestack_arch;
1685 if (tmp != NULL && doublestack2 != NULL) {
1686 if (tmp->
arch == doublestack2) {
1695 if (doublestack != NULL) {
1705 if (repl->special_snow == NULL) {
1709 if (tmp->
arch == repl->special_snow) {
1733 if (tmp->
arch->
name == melt->tile) {
1734 at = melt->special_snow;
1784 int avoid, temp, sky, gotsnow, nodstk;
1785 object *tmp, *oldsnow, *topfloor;
1786 archetype *at, *doublestack, *doublestack2;
1793 if (
rndm(0, 2) > 0) {
1835 if (tmp->
arch->
name == melt->tile) {
1836 at = melt->special_snow;
1846 default: at = NULL;
break;
1854 default: at = NULL;
break;
1860 if (tmp->arch->name != dungmag) {
1867 if (topfloor == NULL) {
1876 if (repl->doublestack_arch != NULL && !nodstk) {
1877 doublestack = repl->doublestack_arch;
1882 if (gotsnow && at) {
1883 if (oldsnow->
arch == at) {
1889 doublestack2 = NULL;
1891 if (repl->doublestack_arch == NULL) {
1896 doublestack2 = repl->doublestack_arch;
1901 if (tmp != NULL && doublestack2 != NULL) {
1902 if (tmp->arch == doublestack2) {
1911 if (doublestack != NULL) {
1937 doublestack2 = NULL;
1939 if (repl->doublestack_arch == NULL) {
1944 doublestack2 = repl->doublestack_arch;
1948 if (tmp != NULL && doublestack2 != NULL) {
1949 if (tmp->
arch == doublestack2) {
1974 int x, y, i, wx, wy;
2070 int x, y, i, wx, wy;
2073 object *tmp, *doublestack;
2080 if (
rndm(0, 2) > 0) {
2278 if ((fp = fopen(filename,
"w")) == NULL) {
2279 LOG(
llevError,
"Cannot open %s for writing\n", filename);
2314 if (!
m || !
m->outdoor)
2337 if (windspeed*2 < wt)
2342 if (
rndm(0, windspeed)+
rndm(0, windspeed) < wt)
2383 int found, is_obj_name, tree_count;
2385 snprintf(filename,
sizeof(filename),
"%s/%s",
settings->
confdir, conf_filename);
2388 "init_config_vals: Could not open file %s. No forestry data is defined. %s\n",
2417 LOG(
llevError,
"init_config_vals: Malformed name entry in %s, line %ld.\n",
2423 found = sscanf(
line,
"%d, %d\n", &is_obj_name, &tree_count);
2426 LOG(
llevError,
"init_config_vals: Malformed forestry entry in %s, line %ld.\n",
2437 frst->
is_obj = is_obj_name;
2468 int found, is_effect;
2470 snprintf(filename,
sizeof(filename),
"%s/%s",
settings->
confdir, conf_filename);
2473 "init_weatheravoid: Could not open file %s. No weatheravoid data is defined. %s\n",
llevError);
2500 LOG(
llevError,
"init_weatheravoid: Malformed name entry in %s, line %ld.\n",
2506 found = sscanf(
line,
"%d\n", &is_effect);
2509 LOG(
llevError,
"init_weatheravoid: Malformed effect flag entry in %s, line %ld.\n",
2520 frst->
snow = is_effect;
2552 snprintf(filename,
sizeof(filename),
"%s/%s",
settings->
confdir, conf_filename);
2582 LOG(
llevError,
"init_weather_replace: Malformed name entry in %s, line %ld.\n",
2592 LOG(
llevError,
"init_weather_replace: Malformed replacement entry in %s, line %ld.\n",
2602 LOG(
llevError,
"init_weather_replace: Malformed doublestack entry in %s, line %ld.\n",
2611 LOG(
llevError,
"init_weatheravoid: Malformed archetype/object flag entry in %s, line %ld.\n",
2623 if (strcmp(repl,
"NONE") == 0)
2628 if (strcmp(doublestack,
"NONE") == 0)
2664 if (!
m || !tx || !ty)
2706 if (!
m || !water || !elev || !trees)
2742 int x, y, tx, ty, nx, ny, ax, ay, j;
2747 int water, space, trees;
2758 water = space = trees = 0;
2766 for (nx = 0, ax = tx; nx < spwtx && ax <
wset.
worldmaptilesizex && space < spwtx*spwty; ax++, nx++) {
2767 for (ny = 0, ay = ty; ny < spwty && ay <
wset.
worldmaptilesizey && space < spwtx*spwty; ay++, ny++, space++) {
2780 if (space < spwtx*spwty) {
2791 for (nx = 0, ax = tx; nx < spwtx && ax <
wset.
worldmaptilesizex && space < spwtx*spwty; ax++, nx++) {
2792 for (ny = j, ay =
MAX(0, ty-(spwty-1)); ny < spwty && ay <= ty && space < spwtx*spwty; space++, ay++, ny++) {
2806 for (ax =
MAX(0, tx-(spwtx-1)); nx < spwtx && ax <= tx && space < spwtx*spwty; ax++, nx++) {
2807 for (ny = 0, ay = ty; ny < spwty && ay <
wset.
worldmaptilesizey && space < spwtx*spwty; ay++, ny++, space++) {
2822 for (nx = 0, ax =
MAX(0, tx - (spwtx-1)); nx < spwtx && ax <= tx && space < spwtx*spwty; ax++, nx++) {
2823 for (ny = j, ay =
MAX(0, ty-(spwty-1)); ny < spwty && ay <= ty && space < spwtx*spwty; space++, ay++, ny++) {
2903 int x, y, tx, starty, ymul, diroffset,
dirdiff;
2935 switch (
rndm(0, 6)) {
3016 switch (
rndm(0, 3)) {
3019 case 2:
if (x) x--;
break;
3020 case 3:
if (y) y--;
break;
3032 n =
rndm(500, 2000);
3044 if ((fp = fopen(
buf,
"r")) == NULL) {
3052 if ((cp = strrchr(
buf,
'\n')) != NULL)
3062 if ((cp = strchr(
buf,
' ')) != NULL) {
3070 int size = atoi(cp);
3073 LOG(
llevError,
"init_weather_settings: worldmaptilesizex must be greater than 1, %d is invalid\n", size);
3077 int size = atoi(cp);
3080 LOG(
llevError,
"init_weather_settings: worldmaptilesizey must be greater than 1, %d is invalid\n", size);
3087 LOG(
llevError,
"init_weather_settings: dynamiclevel must be at least 0, %d is invalid\n", lev);
3093 LOG(
llevError,
"init_weather_settings: line %s ends after specifier, skipping...\n",
buf);
3134 LOG(
llevError,
"Failed to open %s for writing.\n", filename);
3141 fprintf(fp,
"%d ",
weathermap[x][y].forestry);
3167 LOG(
llevError,
"Cannot open %s for writing\n", filename);
3202 LOG(
llevError,
"Cannot open %s for writing\n", filename);
3208 fprintf(fp,
"%d ",
weathermap[x][y].avgelev);
3237 LOG(
llevError,
"Cannot open %s for writing\n", filename);
3268 snprintf(filename,
sizeof(filename),
"%s/temperaturemap",
settings->
localdir);
3271 LOG(
llevError,
"Cannot open %s for writing\n", filename);
3301 snprintf(filename,
sizeof(filename),
"%s/rainfallmap",
settings->
localdir);
3304 LOG(
llevError,
"Cannot open %s for writing\n", filename);
3310 fprintf(fp,
"%u ",
weathermap[x][y].rainfall);
3334 snprintf(filename,
sizeof(filename),
"%s/gulfstreammap",
settings->
localdir);
3337 LOG(
llevError,
"Cannot open %s for writing\n", filename);
3377 snprintf(filename,
sizeof(filename),
"%s/windspeedmap",
settings->
localdir);
3380 LOG(
llevError,
"Cannot open %s for writing\n", filename);
3386 fprintf(fp,
"%hd ",
weathermap[x][y].windspeed);
3413 LOG(
llevError,
"Cannot open %s for writing\n", filename);
3416 LOG(
llevDebug,
"Writing wind direction map to file.\n");
3419 fprintf(fp,
"%d ",
weathermap[x][y].winddir);
3443 snprintf(filename,
sizeof(filename),
"%s/pressuremap",
settings->
localdir);
3446 LOG(
llevError,
"Cannot open %s for writing\n", filename);
3452 fprintf(fp,
"%d ",
weathermap[x][y].pressure);
3475 LOG(
llevError,
"Cannot open %s for writing\n", filename);
3478 LOG(
llevDebug,
"Writing sky conditions map to file.\n");
3558 int32_t min[8], max[8], avgrain, avgwind;
3559 double scale[8], realscalewind;
3561 int64_t total_rainfall = 0;
3562 int64_t total_wind = 0;
3570 min[0] = -100; max[0] = 100;
3571 min[1] = 0; max[1] = 0;
3572 min[2] = 0; max[2] = 0;
3575 min[4] = 0; max[4] = 0;
3577 min[6] = 0; max[6] = 100;
3578 min[7] = -45; max[7] = 45;
3604 assert(avgrain >= 0);
3606 max[2] = avgrain >= 1 ? avgrain-1 : 0;
3607 realscalewind = 255.0l/(max[4]);
3608 max[4] = avgwind >= 1 ? avgwind-1 : 0;
3609 for (x = 0; x < 8; x++) {
3610 scale[x] = 255.0l/(max[x] != min[x] ? max[x] - min[x] : 1);
3618 LOG(
llevError,
"Cannot open %s for writing\n", filename);
3622 fprintf(fp,
"255\n");
3647 if (
weathermap[x][y].rainfall >= uint32_t(avgrain)) {
3664 pressure =
MIN(255,
MAX(0, pressure));
3672 if (
speed < avgwind) {
3718 else if (temp < 20) {
3724 else if (temp < 30) {
3779 int trees, x, y, res;
3782 LOG(
llevDebug,
"Reading forestry data from %s...\n", filename);
3795 res = sscanf(
data,
"%d ", &trees);
3797 LOG(
llevError,
"Forestry data is corrupted and should be regenerated.\n"
3798 "Please delete %s/humidmap and restart the server at your earliest convenience to regenerate the forestry map.\n",
settings->
localdir);
3806 tmp = strpbrk(
data,
" \n");
3810 LOG(
llevError,
"Unexpected end of forestry file. Forestry file may need to be regenerated.\n"
3811 "Please delete %s/humidmap and restart the server at your earliest convenience to regenerate the forestry map.\n",
settings->
localdir);
3845 LOG(
llevDebug,
"Reading humidity data from %s...\n", filename);
3850 LOG(
llevInfo,
"Initializing humidity and elevation maps...\n");
3862 res = sscanf(
data,
"%d ", &hmd);
3864 LOG(
llevError,
"Humidity data is corrupted and cannot be loaded.\n"
3865 "Please delete %s and restart the server to regenerate humidity data.\n", filename);
3872 tmp = strpbrk(
data,
" \n");
3875 "Please delete %s and restart the server to regenerate humidity data.\n", filename);
3906 int x, y, elev, res;
3909 LOG(
llevDebug,
"Reading elevation data from %s...\n", filename);
3921 res = sscanf(
data,
"%d ", &elev);
3923 LOG(
llevError,
"Elevation data is corrupted and cannot be loaded.\n"
3924 "Please delete %s/humidmap and restart your server to regenerate elevation data.\n",
settings->
localdir);
3932 tmp = strpbrk(
data,
" \n");
3934 LOG(
llevError,
"Unexpected end of file in elevation data.\n"
3935 "Please delete %s/humidmap and restart your server to regenerate elevation data.\n",
settings->
localdir);
3968 LOG(
llevDebug,
"Reading water data from %s...\n", filename);
3980 res = sscanf(
data,
"%d ", &wtr);
3982 LOG(
llevError,
"Water map is corrupted and cannot be loaded.\n"
3983 "Please delete %s/humidmap and restart your server to regenerate the water map.\n",
settings->
localdir);
3990 tmp = strpbrk(
data,
" \n");
3992 LOG(
llevError,
"Unexpected end of file in water map.\n"
3993 "Please delete %s/humidmap and restart your server to regenerate the water map.\n",
settings->
localdir);
4024 int16_t temperature;
4026 snprintf(filename,
sizeof(filename),
"%s/temperaturemap",
settings->
localdir);
4027 LOG(
llevDebug,
"Reading temperature data from %s...\n", filename);
4042 res = sscanf(
data,
"%hd ", &temperature);
4044 LOG(
llevError,
"Temperature file is malformed, unable to load temps from file.\n");
4051 tmp = strpbrk(
data,
" \n");
4053 LOG(
llevError,
"Unexpected end of file in temperature map.\n");
4087 snprintf(filename,
sizeof(filename),
"%s/rainfallmap",
settings->
localdir);
4088 LOG(
llevDebug,
"Reading rainfall data from %s...\n", filename);
4105 LOG(
llevError,
"Rainfall file is corrupted, cannot load rainfall from file.\n");
4110 tmp = strpbrk(
data,
" \n");
4112 LOG(
llevError,
"Unexpected end of file in rainfall map.\n");
4144 snprintf(filename,
sizeof(filename),
"%s/gulfstreammap",
settings->
localdir);
4145 LOG(
llevDebug,
"Reading gulf stream data from %s...\n", filename);
4150 LOG(
llevInfo,
"Initializing gulf stream maps...\n");
4162 res = sscanf(
data,
"%d ", &
in);
4164 LOG(
llevError,
"Gulf stream speed definitions are malformed. Cannot load gulf stream from file.\n");
4170 tmp = strpbrk(
data,
" \n");
4172 LOG(
llevError,
"Unexpected end of file in gulfstream speed map.\n");
4186 res = sscanf(
data,
"%d ", &
in);
4188 LOG(
llevError,
"Gulf stream direction definitions are malformed. Cannot load gulf stream from file.\n");
4194 tmp = strpbrk(
data,
" \n");
4196 LOG(
llevError,
"Unexpected end of file in gulfstream direction map.\n");
4209 res = sscanf(
data,
"%d\n", &
in);
4211 LOG(
llevInfo,
"Gulf stream file lacks start position, and is assumed to be old; initializing it randomly.\n");
4241 snprintf(filename,
sizeof(filename),
"%s/windspeedmap",
settings->
localdir);
4242 LOG(
llevDebug,
"Reading wind speed data from %s...\n", filename);
4253 res = sscanf(
data,
"%hhd ", &spd);
4255 LOG(
llevError,
"Wind speed file is malformed. Cannot load wind speed file.\n");
4262 tmp = strpbrk(
data,
" \n");
4264 LOG(
llevError,
"Unexpected end of file in wind speed map.\n");
4296 LOG(
llevDebug,
"Reading wind direction data from %s...\n", filename);
4301 LOG(
llevInfo,
"Initializing wind direction and speed maps...\n");
4314 res = sscanf(
data,
"%d ", &
d);
4316 LOG(
llevError,
"Wind direction map is malformed. Could not load wind direction.\n");
4321 if (d < 1 || d > 8) {
4326 tmp = strpbrk(
data,
" \n");
4328 LOG(
llevError,
"Unexpected end of file in wind direction map.\n");
4360 snprintf(filename,
sizeof(filename),
"%s/pressuremap",
settings->
localdir);
4361 LOG(
llevDebug,
"Reading pressure data from %s...\n", filename);
4377 res = sscanf(
data,
"%hd ", &press);
4379 LOG(
llevError,
"Pressure map is malformed. Could not load pressure.\n");
4386 tmp = strpbrk(
data,
" \n");
4388 LOG(
llevError,
"Unexpected end of file in pressure map.\n");
4422 LOG(
llevDebug,
"Reading current weather position from %s...\n", filename);
4433 res = sscanf(
data,
"%d %d", &sx, &sy);
4438 LOG(
llevError,
"Weather position file was malformed. Using default position.\n");
4479 va_start(args,
type);
4480 code = va_arg(args,
int);
4486 va_arg(args,
object *);
4517 va_start(args,
type);
4518 code = va_arg(args,
int);
4576 va_start(args,
type);
4577 code = va_arg(args,
int);
4580 op = va_arg(args,
object *);
4610 if (pl->type ==
PLAYER) {
4611 pl->contr->do_los = 1;
4616 pl->contr->socket->update_look = 1;
4617 pl->contr->socket->look_position = 0;
4636 int wx, wy, temp, sky;
4641 "The weather is perpetually great around here.");
4645 if (op->
map == NULL)
4650 "You can't see the weather from here.");
4670 "Pressure: %d",
weathermap[wx][wy].pressure);
4673 "Avg Elevation: %d",
weathermap[wx][wy].avgelev);
4681 "It's currently %d degrees Centigrade out.", temp);
4686 buf =
"It is very dry.";
4688 buf =
"It is rather dry.";
4690 buf =
"It is very comfortable today.";
4692 buf =
"It is a bit muggy.";
4694 buf =
"It is muggy.";
4696 buf =
"It is uncomfortably muggy.";
4729 "There is a mild breeze coming from the %s.",
buf);
4732 "There is a strong breeze coming from the %s.",
buf);
4735 "There is a light wind coming from the %s.",
buf);
4738 "There is a strong wind coming from the %s.",
buf);
4741 "There is a heavy wind coming from the %s.",
buf);
4744 "The wind from the %s is incredibly strong!",
buf);
4759 buf =
"There isn't a cloud in the sky.";
4762 buf =
"There are a few light clouds in the sky";
4765 buf =
"The sky is cloudy and dreary.";
4768 buf =
"It is raining softly.";
4771 buf =
"It is raining.";
4774 buf =
"It is raining heavily.";
4777 buf =
"There is a heavy storm! You should go inside!";
4780 buf =
"It's foggy and miserable.";
4783 buf =
"It's hailing out! Take cover!";
4786 buf =
"Snow is gently falling from the sky.";
4789 buf =
"It is snowing out.";
4792 buf =
"Snow is falling very heavily.";
4795 buf =
"A full blown blizzard is in effect. You might want to take cover!";
4925 server->disabled_plugins.push_back(strdup(
"cfweather"));
#define GET_MAP_OB(M, X, Y)
Gets the bottom object on a map.
static void init_wind()
Initialize the wind randomly.
int16_t realtemp
Temperature at a given calculation step for this tile.
int tempmax
Maximum temperature for herb to grow.
int8_t forestry
Range of forestedness.
static const weather_grow_t weather_tile[]
The table below uses the same format as the one above.
struct Settings settings
Global settings.
static void calculate_temperature(mapstruct *m)
Temperature is used in a lot of weather function.
char * bufferreader_data(BufferReader *br)
Get the whole buffer, independently of the calls to bufferreader_next_line().
int load_overlay_map(const char *filename, mapstruct *m)
Loads an overlay for a map, which has been loaded earlier, from file.
size_t bufferreader_current_line(BufferReader *br)
Return the index of the last line returned by bufferreader_next_line().
@ llevError
Problems requiring server admin to fix.
int8_t sky
Sky conditions.
#define EQUATOR_BASE_TEMP
static void init_rainfall()
Initialize rainfall.
#define MOVE_FLYING
Combo of fly_low and fly_high.
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
#define PTICKS_PER_CLOCK
Number of ticks per in-game hour.
weather_avoids_t * next
The next item in the avoid list.
int of_close(OutputFile *of)
Closes an output file.
archetype * special_snow
The archetype name of the tile to place over specified tile.
FILE * of_open(OutputFile *of, const char *fname)
Opens an output file.
void esrv_map_scroll(socket_struct *ns, int dx, int dy)
int blocked_link(object *ob, mapstruct *m, int16_t sx, int16_t sy)
Returns true if the given coordinate is blocked except by the object passed is not blocking.
static void init_pressure()
Reset pressure map.
object * inv
Pointer to the first object in the inventory.
uint16_t look_position
Start of drawing of look window.
mapstruct * ready_map_name(const char *name, int flags)
Makes sure the given map is loaded and swapped in.
int get_world_darkness(void)
Get the darkness of the world map at this point.
#define QUERY_FLAG(xyz, p)
static int read_winddirmap(const Settings *settings)
Read the wind direction.
int32_t avgelev
Average elevation.
int write_rainfallmap(const Settings *settings)
Save rainfall information to localdir.
struct archetype * arch
Pointer to archetype.
int absdir(int d)
Computes an absolute direction.
#define PRESSURE_ROUNDING_FACTOR
int write_humidmap(const Settings *settings)
Save humidity information to localdir.
static void temperature_calc(const int x, const int y, const timeofday_t *tod)
Calculate temperature of a spot.
if you malloc the data for the make sure to free it when done There is also the newclient h file which is shared between the client and server This file contains the definition of the as well as many defined values for constants of varying you will need to grab these constant values for yourself Many of the constants in this file are used in the protocol to denote types Image Caching ~ Image caching has been implemented on the with necessary server support to handle it This section will briefly describe how image caching works on the protocol as well as how the current client does it the client checks for an option denoting the image caching is desired If we initialize all the images to a default value this means we don t need to put special checks into the drawing code to see if we have an image we just draw the default we know what filename to store it as we request the server to do image caching This is done by or ing the cache directive to the image mode we want C when the server finds an image number that it has not send to the it sends us a name command information us the number to name and there is no space between that the and the name Such formating is difficult but the above example illustrates the data is sent The client then checks for the existence of the image locally It is up to the client to organize images and then splits them into sub directories based on the first letters in the above the file would be crossfire images CS CSword If the client does not have the image or otherwise needs a copy from the server
object * transport
Transport the player is in.
#define MAP_IN_MEMORY
Map is fully loaded.
struct mapstruct * map
Pointer to the map in which this object is present.
uint32_t worldmaptilesy
Number of tiles high the worldmap is.
static int read_pressuremap(const Settings *settings)
Read the pressure information from disk.
unsigned char MoveType
Typdef here to define type large enough to hold bitmask of all movement types.
Represents the ingame time.
uint8_t darkness
Indicates level of darkness of map.
#define GULF_STREAM_WIDTH
int16_t pressure
Barometric pressure (mb).
uint32_t worldmapstartx
Starting x tile for the worldmap.
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
#define FLAG_WIZ
Object has special privilegies.
static const weather_grow_t weather_grow[]
The table below is used to grow things on the map.
#define GULF_STREAM_BASE_SPEED
same as sound ncom command like but with extra the client want tick commands so it knows animation timing the client wants to be informed of pickup mode changes Mode will be sent when the player successfully logs in
void bufferreader_destroy(BufferReader *br)
Destroy a BufferReader.
#define MAP_WORLDPARTY(m)
sstring tile
Tile archetype or object name.
int8_t windspeed
Windspeed of this tile.
#define WEATHER_OVERLAY
Weather insert flags.
int random
Random apparition factor.
static int read_gulfstreammap(const Settings *settings)
Read the gulf stream, or initialize it if no saved information.
void object_copy(const object *src_ob, object *dest_ob)
Copy object first frees everything allocated by the second object, and then copies the contents of th...
static void do_map_precipitation(mapstruct *const m)
Do the precipitation for a given map.
void get_tod(timeofday_t *tod)
Computes the ingame time of the day.
static int load_humidity_map_part(mapstruct **m, const int dir, const int x, const int y, int *const tx, int *const ty)
Method to abstract some of the mess of the humidity map.
#define COMMAND_TYPE_NORMAL
Standard commands.
@ TRANSPORT
see doc/Developers/objects
static int read_humidmap(const Settings *settings)
Attempt to read humidity information, or barring that, read the maps and initialize elevation,...
int rndm(int min, int max)
Returns a number between min and max.
int snow
Is this a long-term weather effect, like snow or a puddle? Used for various tests.
static int init_weather_replace(const Settings *settings, const char *conf_filename, weather_replace_t **list)
Load the weather replacement definitions from file.
static int read_windspeedmap(const Settings *settings)
Read the wind speed.
weathermap_t ** weathermap
sstring name
Tile archetype name.
uint32_t pticks
Number of ticks since time reset.
static int worldmap_to_weathermap(const int x, const int y, int *const wx, int *const wy, mapstruct *const m)
Convert coordinates from world map to weather tiles.
object * above
Pointer to the object stacked above this one.
int arch_or_name
If set, tile matches the archetype name, else the object's name.
#define MSG_TYPE_COMMAND
Responses to commands, eg, who.
static void let_it_snow(mapstruct *const m)
Put or remove snow.
This is an overlay structure of the whole world.
static command_registration command_handler
static void plant_a_garden(mapstruct *const m)
Process growth of various plants.
static void init_humid_elev(const Settings *settings)
Initialize humidity, water, forestry, and elevation.
Plugin animator file specs[Config] name
uint32_t worldmaptilesx
Number of tiles wide the worldmap is.
event_registration events_register_global_handler(int eventcode, f_plug_event hook)
Register a global event handler.
int32_t worldmaptilesizey
Number of squares high in a wm tile.
uint32_t update_look
If true, we need to send the look window.
#define PRESSURE_ROUNDING_ITER
static int read_weatherposition(const Settings *settings)
Read the weather map position from file.
static int read_watermap(const Settings *settings)
Load water information from localdir.
int32_t carrying
How much weight this object contains.
weather_replace_t * weather_snowmelt
int16_t y
Position in the map for this object.
static event_registration m
DensityConfig * forest_list
struct player * contr
Pointer to the player which control this object.
BufferReader * bufferreader_init_from_file(BufferReader *br, const char *filepath, const char *failureMessage, LogLevel failureLevel)
Initialize or create a BufferReader from a file path.
static const uint32_t directions[]
Colours used for wind directions.
static int gulf_stream_speed[GULF_STREAM_WIDTH][WEATHERMAPTILESY]
Gulf stream variables.
int write_gulfstreammap(const Settings *settings)
Save the gulf stream to localdir.
static void do_precipitation(mapstruct *const m, const int x, const int y, const int temp, const int sky)
Handle adding precipitation to the map.
void command_unregister(command_registration command)
Unregister a previously registered command.
static int polar_distance(int x, int y, const int equator)
Calculates the distance to the nearest pole.
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
#define WIND_FACTOR
This is a multiplier for the wind caused by pressure differences.
static object * avoid_weather(int *const av, const mapstruct *m, const int x, const int y, int *const gs, const int grow)
Check the current square to see if we should avoid this one for weather processing.
static int read_elevmap(const Settings *settings)
Load the elevation information.
static const uint32_t skies[]
Colours used for weather types.
static void do_weather_insert(mapstruct *const m, int x, int y, const archetype *at, const int8_t object_flags, uint16_t material, int insert_flags)
Do an object insert for weather effects.
int16_t temp
Base temperature of this tile (F).
static int gulf_stream_start
static void plot_gulfstream()
Plot the gulfstream map over the wind map.
void events_unregister_global_handler(int eventcode, event_registration id)
Remove a global event handler.
object clone
An object from which to do object_copy()
void tick_weather()
Do the weather calculations in order.
uint32_t worldmapstarty
Starting y tile for the worldmap.
sstring add_string(const char *str)
Share a string.
weather_avoids_t * growth_avoids
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various what they and how they effect the player s actions Also in this section are the stat modifiers that specific classes professions bring Player and sps the current and maximum the Current and Maximum The Current Sp can go somewhat negative When Sp is negative not all spells can be and a more negative Sp makes spell casting less likey to succeed can affect Damage and how the characters speed
static int wmperformstartx
Current weather tile position.
object * below
Pointer to the object stacked below this one.
static void smooth_pressure()
This code simply smooths the pressure map.
MoveType move_type
Type of movement this object uses.
int write_windspeedmap(const Settings *settings)
Save the wind speed to localdir.
static event_registration global_clock_handler
sstring find_string(const char *str)
Searches a string in the shared strings.
float rfmin
Minimum rainfall for herb to grow (inches/day).
#define MAX_DARKNESS
Maximum map darkness, there is no practical reason to exceed this.
int write_winddirmap(const Settings *settings)
Save wind direction to localdir.
unsigned long todtick
Game world time, in in-game hours.
static void init_temperature()
Initialize the temperature based on the time.
uint8_t type
PLAYER, BULLET, etc.
#define EVENT_CLOCK
Global time event.
#define SAVE_MODE_OVERLAY
Map is persisted as an overlay.
Server as a resource for server administrators and developers the server recognizes the following distinct directories The *name *is what it s called in the server code
void object_free(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects,...
static int read_forestrymap(const Settings *settings)
Read the forestry map from the localdir.
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
#define FLAG_NO_SAVE
If set (through plugins), the object is not saved on maps.
#define INS_ON_TOP
Always put object on top.
archetype * doublestack_arch
If set, this other archetype will be added atop special_snow.
static int get_config_tile(const int x, const int y, const mapstruct *m, const DensityConfig *list)
Get config tile retrieves the desired tile's associated value from a given space.
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
#define EVENT_TIME
Triggered each time the object can react/move.
#define P_OUT_OF_MAP
This space is outside the map.
const char * confdir
Configuration files.
const char * herb
Arch name of item to grow.
static uint8_t wind_blow_object(mapstruct *const m, const int x, const int y, const MoveType move_type, int32_t wt, const living *stats)
Calculate the direction to push an object from wind.
static char * weathermap_to_worldmap_corner(const int wx, const int wy, int *const x, int *const y, const int dir, char *const buffer, const int bufsize)
Return the path of the map in specified direction.
#define FLAG_IS_FLOOR
Can't see what's underneath this object.
static int real_temperature(int x, int y, const timeofday_t *tod)
Compute the real (adjusted) temperature of a given weathermap tile.
void delete_map(mapstruct *m)
Frees the map, including the mapstruct.
int8_t water
-100 - 100 percentage of water tiles.
int similar_direction(int a, int b)
Is direction a similar to direction b? Find out in this exciting function below.
#define FLAG_OVERLAY_FLOOR
Object is an overlay floor.
static event_registration global_map_handler
@ STARTUP_STAGE_BEFORE_SERVER
Called when everything is loaded but before the sockets are opened.
#define INS_NO_WALK_ON
Don't call check_walk_on against the originator.
static void singing_in_the_rain(mapstruct *const m)
Process rain.
static void spin_globe()
The world spinning drags the weather with it.
static void init_gulfstreammap()
Initialize the gulf stream.
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...
Various statistics of objects.
DensityConfig * water_list
void fatal(enum fatal_error err)
fatal() is meant to be called whenever a fatal signal is intercepted.
int real_world_temperature(int x, int y, mapstruct *m)
Compute the temperature for a specific square.
weather_replace_t * weather_replace
#define MAX_BUF
Used for all kinds of things.
#define EVENT_MAPREADY
A map is ready, either first load or after reload.
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
object * object_new(void)
Grabs an object from the list of unused objects, makes sure it is initialised, and returns it.
object * object_insert_in_map(object *op, mapstruct *m, object *originator, int flag)
This function inserts the object in the two-way linked list which represents what is on a map.
int32_t weight
Attributes of the object.
void process_rain()
Keep track of how much rain has fallen in a given weathermap square.
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
void perform_weather()
This routine slowly loads the world, patches it up due to the weather, and saves it back to disk.
#define OUT_OF_REAL_MAP(M, X, Y)
Checks if a square is out of the map.
static int wmperformstarty
Current weather tile position.
int find_dir_2(int x, int y)
Computes a direction which you should travel to move of x and y.
static int write_elevmap(const Settings *settings)
Save the average elevation information to localdir.
uint16_t dynamiclevel
How dynamic is the world?
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 so the higher your the better hidden the runes you make are Examples of whichever way you re facing invoke magic rune transfer as above
static int write_forestrymap(const Settings *settings)
Write the forestry map to the localdir.
#define NDI_UNIQUE
Print immediately, don't buffer.
static event_registration global_object_handler
static const int season_tempchange[HOURS_PER_DAY]
How to alter the temperature, based on the hour of the day.
float rfmax
Maximum rainfall for herb to grow (inches/day).
sstring name
The name of the object, obviously...
int8_t winddir
Direction of wind.
unsigned long event_registration
Registration identifier type.
#define INS_ABOVE_FLOOR_ONLY
Put object immediatly above the floor.
void compute_sky()
Let the madness, begin.
#define FREE_AND_CLEAR(xyz)
Free the pointer and then set it to NULL.
int elevmax
Maximum elevation for herb to grow.
int32_t worldmaptilesizex
Number of squares wide in a wm tile.
int elevmin
Minimum elevation for herb to grow.
int tempmin
Minimum temperature for herb to grow.
uint8_t fastclock
If true, clock goes warp 9.
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
This rolls up wall, blocks_magic, blocks_view, etc, all into one function that just returns a P_.
uint32_t rainfall
Cumulative rainfall.
static int check_replace_match(const object *ob, const weather_replace_t *rep_struct)
Refactor the code to look for arch or object name as it's own code.
static int weather_object_listener(int *type,...)
Global object-process handling for weather.
static void update_humid()
Update the humidity for all weathermap tiles.
const typedef char * sstring
#define EVENT_MAPENTER
A player entered a map.
static int gulf_stream_direction
archetype * find_archetype(const char *name)
Defines a tile the weather system should avoid.
static char * get_next_field(char *line)
Finds the start of the next field in the provided string Skips past interceding commas and spaces.
static void init_weather_settings(Settings *settings)
if you malloc the data for the buffer
#define MSG_TYPE_COMMAND_WEATHER
Structure to hold density data entries.
#define CLEAR_FLAG(xyz, p)
int humin
Minimum humidity for herb to grow.
int write_skymap(void)
Write the sky map.
static int read_temperaturemap(const Settings *settings)
Load or initialize temperature information.
#define MAP_WORLDPARTX(m)
#define INS_NO_MERGE
Don't try to merge with other items.
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various stats
====Textual A command containing textual data has data fields separated by one ASCII space character. word::A sequence of ASCII characters that does not contain the space or nul character. This is to distinguish it from the _string_, which may contain space characters. Not to be confused with a machine word. int::A _word_ containing the textual representation of an integer. Not to be confused with any of the binary integers in the following section. Otherwise known as the "string value of integer data". Must be parsed, e.g. using `atoi()` to get the actual integer value. string::A sequence of ASCII characters. This must only appear at the end of a command, since spaces are used to separate fields of a textual message.=====Binary All multi-byte integers are transmitted in network byte order(MSB first). int8::1-byte(8-bit) integer int16::2-byte(16-bit) integer int32::4-byte(32-bit) integer lstring::A length-prefixed string, which consists of an `int8` followed by that many bytes of the actual string. This is used to transmit a string(that may contain spaces) in the middle of binary data. l2string::Like _lstring_, but is prefixed with an `int16` to support longer strings Implementation Notes ~~~~~~~~~~~~~~~~~~~~ - Typical implementations read two bytes to determine the length of the subsequent read for the actual message, then read and parse the data from each message according to the commands described below. To send a message, the sender builds the message in a buffer, counts the length of the message, sends the length, and finally sends the actual message. TIP:Incorrectly transmitting or receiving the `length` field can lead to apparent "no response" issues as the client or server blocks to read the entire length of the message. - Since the protocol is highly interactive, it may be useful to set `TCP_NODELAY` on both the client and server. - If you are using a language with a buffered output stream, remember to flush the stream after a complete message. - If the connection is lost(which will also happen if the output buffer overflowing), the player is saved and the server cleans up. This does open up some abuses, but there is no perfect solution here. - The server only reads data from the socket if the player has an action. This isn 't really good, since many of the commands below might not be actual commands for the player. The alternative is to look at the data, and if it is a player command and there isn 't time, store it away to be processed later. But this increases complexity, in that the server must start buffering the commands. Fortunately, for now, there are few such client commands. Commands -------- In the documentation below, `S->C` represents a message to the client from the server, and `C->S` represents a message to the server from the client. Commands are documented in a brief format like:C->S:version< csval >[scval[vinfo]] Fields are enclosed like `< this >`. Optional fields are denoted like `[this]`. Spaces that appear in the command are literal, i.e. the<< _version > > command above uses spaces to separate its fields, but the command below does not:C->S:accountlogin< name >< password > As described in<< _messages > >, if a command contains data, then the command is separated from the data by a literal space. Many of the commands below refer to 'object tags'. Whenever the server creates an object, it creates a unique tag for that object(starting at 1 when the server is first run, and ever increasing.) Tags are unique, but are not consistent between runs. Thus, the client can not store tags when it exits and hope to re-use them when it joins the server at a later time - tags are only valid for the current connection. The protocol commands are broken into various sections which based somewhat on what the commands are for(ie, item related commands, map commands, image commands, etc.) In this way, all the commands related to similar functionality is in the same place. Initialization ~~~~~~~~~~~~~~ version ^^^^^^^ C->S:version< csval >[scval[vinfo]] S->C:version< csval >[scval[vinfo]] Used by the client and server to exchange which version of the Crossfire protocol they understand. Neither send this in response to the other - they should both send this shortly after a connection is established. csval::int, version level of C->S communications scval::int, version level of S->C communications vinfo::string, that is purely for informative that general client/server info(ie, javaclient, x11client, winclient, sinix server, etc). It is purely of interest of server admins who can see what type of clients people are using.=====Version ID If a new command is added to the protocol in the C->S direction, then the version number in csval will get increased. Likewise, the same is true for the scval. The version are currently integers, in the form ABCD. A=1, and will likely for quite a while. This will only really change if needed from rollover of B. B represents major protocol changes - if B mismatches, the clients will be totally unusable. Such an example would be change of map or item sending commands(either new commands or new format.) C represents more minor but still significant changes - clients might still work together, but some features that used to work may now fail due to the mismatch. An example may be a change in the meaning of some field in some command - providing the field is the same size, it still should be decoded properly, but the meaning won 't be processed properly. D represents very minor changes or new commands. Things should work no worse if D does not match, however if they do match, some new features might be included. An example of the would be the C->S mark command to mark items. Server not understanding this just means that the server can not process it, and will ignore it.=====Handling As far as the client is concerned, its _scval_ must be at least equal to the server, and its _csval_ should not be newer than the server. The server does not care about the version command it receives right now - all it currently does is log mismatches. In theory, the server should keep track of what the client has, and adjust the commands it sends respectively in the S->C direction. The server is resilant enough that it won 't crash with a version mismatch(however, client may end up sending commands that the server just ignores). It is really up to the client to enforce versioning and quit if the versions don 't match. NOTE:Since all packets have the length as the first 2 bytes, all that either the client or server needs to be able to do is look at the first string and see if it understands it. If not, it knows how many bytes it can skip. As such, exact version matches should not be necessary for proper operation - however, both the client and server needs to be coded to handle such cases.=====History _scval_ and _vinfo_ were added in version 1020. Before then, there was only one version sent in the version command. NOTE:For the most part, this has been obsoleted by the setup command which always return status and whether it understood the command or not. However there are still some cases where using this versioning is useful - an example it the addition of the requestinfo/replyinfo commands - the client wants to wait for acknowledge of all the replyinfo commands it has issued before sending the addme command. However, if the server doesn 't understand these options, the client will never get a response. With the versioning, the client can look at the version and know if it should wait for a response or if the server will never send back. setup ^^^^^ C->S, S->C:setup< option1 >< value1 >< option2 >< value2 > ... Sent by the client to request protocol option changes. This can be at any point during the life of a connection, but usually sent at least once right after the<< _version > > command. The server responds with a message in the same format confirming what configuration options were set. The server only sends a setup command in response to one from the client. The sc_version should be updated in the server if commands have been obsoleted such that old clients may not be able to play. option::word, name of configuration option value::word, value of configuration option. May need further parsing according to the setup options below=====Setup Options There are really 2 set of setup commands here:. Those that control preferences of the client(how big is the map, what faceset to use, etc). . Those that describe capabilities of the client(client supports this protocol command or that) .Setup Options[options="autowidth,header"]|===========================|Command|Description|beat|Ask the server to enable heartbeat support. When heartbeat is enabled, the client must send the server a command every three seconds. If no commands need to be sent, use the `beat` no-op command. Clients that do not contact the server within the interval are assumed to have a temporary connection failure.|bot(0/1 value)|If set to 1, the client will not be considered a player when updating information to the metaserver. This is to avoid having a server with many bots appear more crowded than others.|darkness(0/1 value)|If set to 1(default), the server will send darkness information in the map protocol commands. If 0, the server will not include darkness, thus saving a minor amount of bandwidth. Since the client is free to ignore the darkness information, this does not allow the client to cheat. In the case of the old 'map' protocol command, turning darkness off will result in the masking faces not getting sent to the client.|extended_stats(0/1 value)|If set to 1, the server will send the CS_STAT_RACE_xxx and CS_STAT_BASE_xxx values too, so the client can display various status related to statistics. Default is 0.|facecache(0/1)|Determines if the client is caching images(1) or wants the images sent to it without caching them(0). Default is 0. This replaces the setfacemode command.|faceset(8 bit)|Faceset the client wishes to use. If the faceset is not valid, the server returns the faceset the client will be using(default 0).|loginmethod(8 bit)|Client sends this to server to note login support. This is basically used as a subset of the csversion/scversion to find out what level of login support the server and client support. Current defined values:0:no advanced support - only legacy login method 1:account based login(described more below) 2:new character creation support This list may grow - for example, advanced character creation could become a feature.|map2cmd:(1)|This indicates client support for the map2 protocol command. See the map2 protocol details above for the main differences. Obsolete:This is the only supported mode now, but many clients use it as a sanity check for protocol versions, so the server still replies. It doesn 't do anything with the data|mapsize(int x) X(int y)|Sets the map size to x X y. Note the spaces here are only for clarity - there should be no spaces when actually sent(it should be 11x11 or 25x25). The default map size unless changed is 11x11. The minimum map size the server will allow is 9x9(no technical reason this could be smaller, but I don 't think the game would be smaller). The maximum map size supported in the current protocol is 63x63. However, each server can have its maximum map size sent to most any value. If the client sends an invalid mapsize command or a mapsize of 0x0, the server will respond with a mapsize that is the maximum size the server supports. Thus, if the client wants to know the maximum map size, it can just do a 'mapsize 0x0' or 'mapsize' and it will get the maximum size back. The server will constrain the provided mapsize x &y to the configured minumum and maximums. For example, if the maximum map size is 25x25, the minimum map size is 9x9, and the client sends a 31x7 mapsize request, the mapsize will be set to 25x9 and the server will send back a mapsize 25x9 setup command. When the values are valid, the server will send back a mapsize XxY setup command. Note that this is from its parsed values, so it may not match stringwise with what the client sent, but will match 0 wise. For example, the client may send a 'mapsize 025X025' command, in which case the server will respond with a 'mapsize 25x25' command - the data is functionally the same. The server will send an updated map view when this command is sent.|notifications(int value)|Value indicating what notifications the client accepts. It is incremental, a value means "all notifications till this level". The following levels are supported:1:quest-related notifications("addquest" and "updquest") 2:knowledge-related notifications("addknowledge") 3:character status flags(overloaded, blind,...)|num_look_objects(int value)|The maximum number of objects shown in the ground view. If more objects are present, fake objects are created for selecting the previous/next group of items. Defaults to 50 if not set. The server may adjust the given value to a suitable one data
static void smooth_wind()
It doesn't really smooth it as such.
int strcasecmp(const char *s1, const char *s2)
int write_pressuremap(const Settings *settings)
Save pressure information to localdir.
int humax
Maximum humidity for herb to grow.
static int read_rainfallmap(const Settings *settings)
Read or initialize rainfall information.
Weather settings definition structure Stolen from the settings file, as they are unused by everything...
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
int write_temperaturemap(const Settings *settings)
Save temperature information to localdir.
static void command_weather(object *op, const char *)
Player is wondering about the weather.
command_registration command_register(const char *name, uint8_t type, command_function func, float time)
Register a player-issued command.
static int weather_listener(int *type,...)
Global event handling for weather.
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to.
#define EVENT_MAPLOAD
A map is loaded (pristine state)
uint64_t command_registration
Identifier when registering a command.
int season
Season the herb can grow.
weather_avoids_t * weather_avoids
Defines a tile the weather system can change to another tile.
Defines a tile where something can grow.
static int write_watermap(const Settings *settings)
Save water percent information to localdir.
static void weather_effect(mapstruct *const m)
Perform actual effect of weather.
static weather_settings_t wset
int save_map(mapstruct *m, int flag)
Saves a map to file.
static void change_the_world(mapstruct *const m)
Process worldmap regrowth.
int8_t humid
Humitidy of this tile.
sstring name
More definite name, like "generate_kobold".
#define PRESSURE_ITERATIONS
socket_struct * socket
Socket information for this player.
living stats
Str, Con, Dex, etc.
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
static int init_config_vals(const Settings *settings, const char *conf_filename, DensityConfig **list)
Read a config file that tells how many units (for an arbitrary purpose) a given arch is worth during ...
const char * tile
Arch tile to grow on, NULL if anything.
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
static int gulf_stream_dir[GULF_STREAM_WIDTH][WEATHERMAPTILESY]
Direction of the gulf stream.
static int weather_clock_listener(int *type,...)
Global clock event handling for weather.
static const char * days[]
Ingame days.
mapstruct * mapfile_load(const char *map, int flags)
Opens the file "filename" and reads information about the map from the given file,...
weather_replace_t * weather_evaporate
void cfweather_init(Settings *settings, ServerSettings *server, StartupStage stage)
Weather module initialisation.
int dirdiff(int dir1, int dir2)
Computes a direction difference.
uint16_t material
What materials this object consist of.
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
static int humid_tile(const int x, const int y, const int dark)
Calculate the humidity of the given weather tile.
weather_replace_t * next
The next item in the replace list.
int write_weather_images()
Dump all the weather data as an image.
@ llevDebug
Only for debugging purposes.
static int do_water_elev_calc(mapstruct *const m, const int x, const int y, int *const water, int64_t *const elev, int *const trees)
Do the water and elevation updates on the given map tile.
static void perform_pressure()
Perform small randomizations in the pressure map.
char * bufferreader_next_line(BufferReader *br)
Return the next line in the buffer, as separated by a newline.
int players_on_map(mapstruct *m, int show_all)
Returns the count of players on a map, calculated from player list.
static int init_weatheravoid(const Settings *settings, const char *conf_filename, weather_avoids_t **wa)
Load the weather/growth avoid defintions from file.
const char * localdir
Read/write data files.