version 1.12 | | version 1.13 |
---|
| | |
/* | | /* |
* static char *rcsid_weather_c = | | * static char *rcsid_weather_c = |
* "$Id: weather.c,v 1.12 2002/11/06 09:47:23 garbled Exp $"; | | * "$Id: weather.c,v 1.13 2002/11/08 08:54:07 garbled Exp $"; |
*/ | | */ |
/* | | /* |
CrossFire, A Multiplayer game for X-windows | | CrossFire, A Multiplayer game for X-windows |
| | |
extern unsigned long todtick; | | extern unsigned long todtick; |
extern weathermap_t **weathermap; | | extern weathermap_t **weathermap; |
| | |
#define POLAR_BASE_TEMP 0 /* C */ | | |
#define EQUATOR_BASE_TEMP 25 /* C */ | | |
#define SEASONAL_ADJUST 10 /* polar distance */ | | |
#define GULF_STREAM_WIDTH 3 /* width of gulf stream */ | | |
#define GULF_STREAM_BASE_SPEED 40 /* base speed of gulf stream */ | | |
| | |
/* don't muck with these unless you are sure you know what they do */ | | |
#define PRESSURE_ITERATIONS 30 | | |
#define PRESSURE_AREA 180 | | |
#define PRESSURE_ROUNDING_FACTOR 2 | | |
#define PRESSURE_ROUNDING_ITER 1 | | |
#define PRESSURE_SPIKES 3 | | |
#define PRESSURE_MAX 1040 | | |
#define PRESSURE_MIN 960 | | |
| | |
/* editing the below might require actual changes to code */ | | |
#define WEATHERMAPTILESX 100 | | |
#define WEATHERMAPTILESY 100 | | |
| | |
/* sky conditions */ | | |
#define SKY_CLEAR 0 | | |
#define SKY_LIGHTCLOUD 1 | | |
#define SKY_OVERCAST 2 | | |
#define SKY_LIGHT_RAIN 3 | | |
#define SKY_RAIN 4 /* rain -> storm has lightning */ | | |
#define SKY_HEAVY_RAIN 5 | | |
#define SKY_HURRICANE 6 | | |
/* wierd weather 7-12 */ | | |
#define SKY_FOG 7 | | |
#define SKY_HAIL 8 | | |
/* snow */ | | |
#define SKY_LIGHT_SNOW 13 /* add 10 to rain to get snow */ | | |
#define SKY_SNOW 14 | | |
#define SKY_HEAVY_SNOW 15 | | |
#define SKY_BLIZZARD 16 | | |
| | |
int gulf_stream_speed[GULF_STREAM_WIDTH][WEATHERMAPTILESY]; | | int gulf_stream_speed[GULF_STREAM_WIDTH][WEATHERMAPTILESY]; |
int gulf_stream_dir[GULF_STREAM_WIDTH][WEATHERMAPTILESY]; | | int gulf_stream_dir[GULF_STREAM_WIDTH][WEATHERMAPTILESY]; |
int gulf_stream_start; | | int gulf_stream_start; |
| | |
} | | } |
delete_map(m); | | delete_map(m); |
/* jesus thats confusing as all hell */ | | /* jesus thats confusing as all hell */ |
printf("water %d humid %d\n", water, water*100/(spwtx*spwty)); | | |
weathermap[x][y].humid = water*100/(spwtx*spwty); | | weathermap[x][y].humid = water*100/(spwtx*spwty); |
weathermap[x][y].avgelev = elev/(spwtx*spwty); | | weathermap[x][y].avgelev = elev/(spwtx*spwty); |
weathermap[x][y].water = weathermap[x][y].humid; | | weathermap[x][y].water = weathermap[x][y].humid; |
| | |
return; | | return; |
| | |
/* move right to left, top to bottom */ | | /* move right to left, top to bottom */ |
if (wmperformstartx == settings.worldmaptilesx) { | | if (wmperformstartx+1 == settings.worldmaptilesx) { |
wmperformstartx = 0; | | wmperformstartx = 0; |
wmperformstarty++; | | wmperformstarty++; |
} else | | } else |
| | |
return; | | return; |
| | |
let_it_snow(m, wx, wy, filename); | | let_it_snow(m, wx, wy, filename); |
| | singing_in_the_rain(m, wx, wy, filename); |
| | |
} | | } |
| | |
void let_it_snow(mapstruct *m, int wx, int wy, char *filename) | | object *avoid_weather(int *av, mapstruct *m, int x, int y, int *gs) |
{ | | { |
int x, y; | | int avoid, gotsnow; |
int avoid, two, temp, sky, gotsnow; | | object *tmp; |
object *ob, *tmp, *oldsnow; | | |
archetype *at; | | |
| | |
for (x=0; x < settings.worldmaptilesizex; x++) { | | |
for (y=0; y < settings.worldmaptilesizey; y++) { | | |
(void)worldmap_to_weathermap(x, y, &wx, &wy, filename); | | |
ob = NULL; | | |
at = NULL; | | |
/* this will definately need tuning */ | | |
avoid = 0; | | avoid = 0; |
two = 0; | | |
gotsnow = 0; | | gotsnow = 0; |
temp = real_world_temperature(x, y, m); | | |
sky = weathermap[wx][wy].sky; | | |
if (temp <= 0 && sky > SKY_OVERCAST && sky < SKY_FOG) | | |
sky += 10; /*let it snow*/ | | |
for (tmp=GET_MAP_OB(m, x, y); tmp; tmp = tmp->above) { | | for (tmp=GET_MAP_OB(m, x, y); tmp; tmp = tmp->above) { |
/* problem: snow never gets upgraded */ | | |
if (!strcmp(tmp->arch->name, "snow")) { | | if (!strcmp(tmp->arch->name, "snow")) { |
gotsnow++; | | gotsnow++; |
oldsnow = tmp; | | break; |
} else if (!strcmp(tmp->arch->name, "snow2")) { | | } else if (!strcmp(tmp->arch->name, "snow2")) { |
gotsnow++; | | gotsnow++; |
oldsnow = tmp; | | break; |
} else if (!strcmp(tmp->arch->name, "snow4")) { | | } else if (!strcmp(tmp->arch->name, "snow4")) { |
gotsnow++; | | gotsnow++; |
oldsnow = tmp; | | break; |
| | } else if (!strcmp(tmp->arch->name, "rain1")) { |
| | gotsnow++; |
| | break; |
| | } else if (!strcmp(tmp->arch->name, "rain2")) { |
| | gotsnow++; |
| | break; |
| | } else if (!strcmp(tmp->arch->name, "rain3")) { |
| | gotsnow++; |
| | break; |
| | } else if (!strcmp(tmp->arch->name, "rain4")) { |
| | gotsnow++; |
| | break; |
| | } else if (!strcmp(tmp->arch->name, "rain5")) { |
| | gotsnow++; |
| | break; |
} else if (!strcmp(tmp->name, "drifts")) | | } else if (!strcmp(tmp->name, "drifts")) |
avoid++; | | avoid++; |
else if (!strcmp(tmp->arch->name, "cforest1")) | | else if (!strcmp(tmp->arch->name, "cforest1")) |
| | |
else if (!strcmp(tmp->name, "shallow_sea")) | | else if (!strcmp(tmp->name, "shallow_sea")) |
avoid++; | | avoid++; |
} | | } |
| | *gs = gotsnow; |
| | *av = avoid; |
| | return tmp; |
| | } |
| | |
| | void let_it_snow(mapstruct *m, int wx, int wy, char *filename) |
| | { |
| | int x, y; |
| | int avoid, two, temp, sky, gotsnow; |
| | object *ob, *tmp, *oldsnow; |
| | archetype *at; |
| | |
| | for (x=0; x < settings.worldmaptilesizex; x++) { |
| | for (y=0; y < settings.worldmaptilesizey; y++) { |
| | (void)worldmap_to_weathermap(x, y, &wx, &wy, filename); |
| | ob = NULL; |
| | at = NULL; |
| | /* this will definately need tuning */ |
| | avoid = 0; |
| | two = 0; |
| | gotsnow = 0; |
| | temp = real_world_temperature(x, y, m); |
| | sky = weathermap[wx][wy].sky; |
| | if (temp <= 0 && sky > SKY_OVERCAST && sky < SKY_FOG) |
| | sky += 10; /*let it snow*/ |
| | oldsnow = avoid_weather(&avoid, m, x, y, &gotsnow); |
if (!avoid) { | | if (!avoid) { |
if (sky >= SKY_LIGHT_SNOW && sky < SKY_HEAVY_SNOW) | | if (sky >= SKY_LIGHT_SNOW && sky < SKY_HEAVY_SNOW) |
at = find_archetype("snow"); | | at = find_archetype("snow"); |
| | |
if (!strcmp(GET_MAP_OB(m, x, y)->name, "hills") && | | if (!strcmp(GET_MAP_OB(m, x, y)->name, "hills") && |
sky >= SKY_LIGHT_SNOW) | | sky >= SKY_LIGHT_SNOW) |
at = find_archetype("drifts"); | | at = find_archetype("drifts"); |
| | /* special case scorn, where the no-magic field wrecks my |
| | logic */ |
| | if (GET_MAP_OB(m, x, y)->above != NULL) { |
| | if (!strcmp(GET_MAP_OB(m, x, y)->above->name, |
| | "cobblestones") && sky >= SKY_LIGHT_SNOW) |
| | at = find_archetype("snow4"); |
| | if (!strcmp(GET_MAP_OB(m, x, y)->above->arch->name, |
| | "cobblestones2") && sky >= SKY_LIGHT_SNOW) |
| | at = find_archetype("snow4"); |
| | } |
if (!strcmp(GET_MAP_OB(m, x, y)->name, "cobblestones") && | | if (!strcmp(GET_MAP_OB(m, x, y)->name, "cobblestones") && |
sky >= SKY_LIGHT_SNOW) | | sky >= SKY_LIGHT_SNOW) |
at = find_archetype("snow4"); | | at = find_archetype("snow4"); |
| | |
two++; | | two++; |
if (!strcmp(GET_MAP_OB(m, x, y)->name, "tree")) | | if (!strcmp(GET_MAP_OB(m, x, y)->name, "tree")) |
two++; | | two++; |
| | if (!strcmp(GET_MAP_OB(m, x, y)->arch->name, "woods")) |
| | two++; |
| | if (!strcmp(GET_MAP_OB(m, x, y)->arch->name, "woods_3")) |
| | two++; |
if (gotsnow && at) { | | if (gotsnow && at) { |
if (!strcmp(oldsnow->arch->name, at->name)) | | if (!strcmp(oldsnow->arch->name, at->name)) |
at = NULL; | | at = NULL; |
| | |
tmp = tmp->above; | | tmp = tmp->above; |
else if (!strcmp(tmp->name, "tree")) | | else if (!strcmp(tmp->name, "tree")) |
tmp = tmp->above; | | tmp = tmp->above; |
| | else if (!strcmp(tmp->arch->name, "woods")) |
| | tmp = tmp->above; |
| | else if (!strcmp(tmp->arch->name, "woods_3")) |
| | tmp = tmp->above; |
if (tmp != NULL) | | if (tmp != NULL) |
if (strcmp(tmp->arch->name, "tree3") == 0 || | | if (strcmp(tmp->arch->name, "tree3") == 0 || |
strcmp(tmp->arch->name, "tree5") == 0) { | | strcmp(tmp->arch->name, "tree5") == 0 || |
| | strcmp(tmp->arch->name, "woods4") == 0 || |
| | strcmp(tmp->arch->name, "woods5") == 0) { |
remove_ob(tmp); | | remove_ob(tmp); |
free_object(tmp); | | free_object(tmp); |
} | | } |
| | |
copy_object(&at->clone, ob); | | copy_object(&at->clone, ob); |
ob->x = x; | | ob->x = x; |
ob->y = y; | | ob->y = y; |
| | ob->material = M_ICE; |
if (!strcmp(ob->arch->name, "snow4")) | | if (!strcmp(ob->arch->name, "snow4")) |
SET_FLAG(ob, FLAG_OVERLAY_FLOOR); | | SET_FLAG(ob, FLAG_OVERLAY_FLOOR); |
insert_ob_in_map(ob, m, ob, | | insert_ob_in_map(ob, m, ob, |
INS_NO_MERGE | INS_NO_WALK_ON | INS_ABOVE_FLOOR_ONLY); | | INS_NO_MERGE | INS_NO_WALK_ON | INS_ABOVE_FLOOR_ONLY); |
if (two) { | | if (two) { |
| | at = NULL; |
if (!strcmp(GET_MAP_OB(m, x, y)->name, "evergreen")) | | if (!strcmp(GET_MAP_OB(m, x, y)->name, "evergreen")) |
at = find_archetype("tree5"); | | at = find_archetype("tree5"); |
if (!strcmp(GET_MAP_OB(m, x, y)->name, "tree")) | | if (!strcmp(GET_MAP_OB(m, x, y)->name, "tree")) |
at = find_archetype("tree3"); | | at = find_archetype("tree3"); |
| | if (!strcmp(GET_MAP_OB(m, x, y)->arch->name, "woods")) |
| | at = find_archetype("woods4"); |
| | if (!strcmp(GET_MAP_OB(m, x, y)->arch->name, "woods3")) |
| | at = find_archetype("woods5"); |
| | if (at != NULL) { |
ob = get_object(); | | ob = get_object(); |
copy_object(&at->clone, ob); | | copy_object(&at->clone, ob); |
ob->x = x; | | ob->x = x; |
| | |
} | | } |
} | | } |
} | | } |
| | } |
if (temp > 8) { | | if (temp > 8) { |
/* melt some snow */ | | /* melt some snow */ |
for (tmp=GET_MAP_OB(m, x, y)->above; tmp; tmp = tmp->above) { | | for (tmp=GET_MAP_OB(m, x, y)->above; tmp; tmp = tmp->above) { |
| | |
else if (!strcmp(tmp->arch->name, "glacier")) | | else if (!strcmp(tmp->arch->name, "glacier")) |
avoid++; | | avoid++; |
if (avoid) { | | if (avoid) { |
| | /* replace snow with a big puddle */ |
remove_ob(tmp); | | remove_ob(tmp); |
free_object(tmp); | | free_object(tmp); |
tmp=GET_MAP_OB(m, x, y); | | at = find_archetype("rain5"); |
/* clean up the trees we put over the snow */ | | if (at != NULL) { |
if (!strcmp(tmp->name, "evergreen")) | | ob = get_object(); |
tmp = tmp->above; | | copy_object(&at->clone, ob); |
else if (!strcmp(tmp->name, "tree")) | | ob->x = x; |
tmp = tmp->above; | | ob->y = y; |
if (tmp != NULL) | | SET_FLAG(ob, FLAG_OVERLAY_FLOOR); |
if (strcmp(tmp->arch->name, "tree3") == 0 || | | ob->material = M_LIQUID; |
strcmp(tmp->arch->name, "tree5") == 0) { | | insert_ob_in_map(ob, m, ob, INS_NO_MERGE | |
remove_ob(tmp); | | INS_NO_WALK_ON | INS_ABOVE_FLOOR_ONLY); |
free_object(tmp); | | |
} | | } |
break; | | |
} | | } |
} | | } |
} | | } |
| | |
} | | } |
} | | } |
| | |
| | void singing_in_the_rain(mapstruct *m, int wx, int wy, char *filename) |
| | { |
| | int x, y; |
| | int avoid, two, temp, sky, gotsnow; |
| | object *ob, *tmp, *oldsnow; |
| | archetype *at; |
| | |
| | for (x=0; x < settings.worldmaptilesizex; x++) { |
| | for (y=0; y < settings.worldmaptilesizey; y++) { |
| | (void)worldmap_to_weathermap(x, y, &wx, &wy, filename); |
| | ob = NULL; |
| | at = NULL; |
| | avoid = 0; |
| | two = 0; |
| | gotsnow = 0; |
| | temp = real_world_temperature(x, y, m); |
| | sky = weathermap[wx][wy].sky; |
| | /* it's probably allready snowing */ |
| | if (temp < 0) |
| | continue; |
| | oldsnow = avoid_weather(&avoid, m, x, y, &gotsnow); |
| | if (!avoid) { |
| | if (sky == SKY_LIGHT_RAIN || sky == SKY_RAIN) |
| | switch (rndm(0, SKY_HAIL-sky)) { |
| | case 0: at = find_archetype("rain1"); break; |
| | case 1: at = find_archetype("rain2"); break; |
| | default: at = NULL; |
| | } |
| | if (sky >= SKY_HEAVY_RAIN && sky <= SKY_HURRICANE) |
| | switch (rndm(0, SKY_HAIL-sky)) { |
| | case 0: at = find_archetype("rain3"); break; |
| | case 1: at = find_archetype("rain4"); break; |
| | case 2: at = find_archetype("rain5"); break; |
| | default: at = NULL; |
| | } |
| | if (!strcmp(GET_MAP_OB(m, x, y)->name, "evergreen")) |
| | two++; |
| | if (!strcmp(GET_MAP_OB(m, x, y)->name, "tree")) |
| | two++; |
| | if (!strcmp(GET_MAP_OB(m, x, y)->arch->name, "woods")) |
| | two++; |
| | if (!strcmp(GET_MAP_OB(m, x, y)->arch->name, "woods_3")) |
| | two++; |
| | if (gotsnow && at) { |
| | if (!strcmp(oldsnow->arch->name, at->name)) |
| | at = NULL; |
| | else { |
| | remove_ob(oldsnow); |
| | free_object(oldsnow); |
| | tmp=GET_MAP_OB(m, x, y); |
| | /* clean up the trees we put over the snow */ |
| | if (!strcmp(tmp->name, "evergreen")) |
| | tmp = tmp->above; |
| | else if (!strcmp(tmp->name, "tree")) |
| | tmp = tmp->above; |
| | else if (!strcmp(tmp->arch->name, "woods")) |
| | tmp = tmp->above; |
| | else if (!strcmp(tmp->arch->name, "woods_3")) |
| | tmp = tmp->above; |
| | if (tmp != NULL) |
| | if (strcmp(tmp->arch->name, "tree3") == 0 || |
| | strcmp(tmp->arch->name, "tree5") == 0 || |
| | strcmp(tmp->arch->name, "woods4") == 0 || |
| | strcmp(tmp->arch->name, "woods5") == 0) { |
| | remove_ob(tmp); |
| | free_object(tmp); |
| | } |
| | } |
| | } |
| | if (at != NULL) { |
| | ob = get_object(); |
| | copy_object(&at->clone, ob); |
| | ob->x = x; |
| | ob->y = y; |
| | SET_FLAG(ob, FLAG_OVERLAY_FLOOR); |
| | ob->material = M_LIQUID; |
| | insert_ob_in_map(ob, m, ob, |
| | INS_NO_MERGE | INS_NO_WALK_ON | INS_ABOVE_FLOOR_ONLY); |
| | if (two) { |
| | at = NULL; |
| | if (!strcmp(GET_MAP_OB(m, x, y)->name, "evergreen")) |
| | at = find_archetype("tree5"); |
| | if (!strcmp(GET_MAP_OB(m, x, y)->name, "tree")) |
| | at = find_archetype("tree3"); |
| | if (!strcmp(GET_MAP_OB(m, x, y)->arch->name, "woods")) |
| | at = find_archetype("woods4"); |
| | if (!strcmp(GET_MAP_OB(m, x, y)->arch->name, "woods3")) |
| | at = find_archetype("woods5"); |
| | if (at != NULL) { |
| | ob = get_object(); |
| | copy_object(&at->clone, ob); |
| | ob->x = x; |
| | ob->y = y; |
| | insert_ob_in_map(ob, m, ob, |
| | INS_NO_MERGE | INS_NO_WALK_ON | INS_ON_TOP); |
| | } |
| | } |
| | } |
| | } |
| | /* Things evaporate fast in the heat */ |
| | if (temp > 8 && sky < SKY_OVERCAST && rndm(temp, 60) > 50) { |
| | /* evaporate */ |
| | for (tmp=GET_MAP_OB(m, x, y)->above; tmp; tmp = tmp->above) { |
| | avoid = 0; |
| | if (!strcmp(tmp->arch->name, "rain1")) |
| | avoid++; |
| | else if (!strcmp(tmp->arch->name, "rain2")) |
| | avoid++; |
| | else if (!strcmp(tmp->arch->name, "rain3")) |
| | avoid++; |
| | else if (!strcmp(tmp->arch->name, "rain4")) |
| | avoid++; |
| | else if (!strcmp(tmp->arch->name, "rain5")) |
| | avoid++; |
| | if (avoid) { |
| | remove_ob(tmp); |
| | free_object(tmp); |
| | if (weathermap[wx][wy].humid < 100 && rndm(0, 50) == 0) |
| | weathermap[wx][wy].humid++; |
| | tmp=GET_MAP_OB(m, x, y); |
| | /* clean up the trees we put over the rain */ |
| | if (!strcmp(tmp->name, "evergreen")) |
| | tmp = tmp->above; |
| | else if (!strcmp(tmp->name, "tree")) |
| | tmp = tmp->above; |
| | else if (!strcmp(tmp->arch->name, "woods")) |
| | tmp = tmp->above; |
| | else if (!strcmp(tmp->arch->name, "woods_3")) |
| | tmp = tmp->above; |
| | if (tmp != NULL) |
| | if (strcmp(tmp->arch->name, "tree3") == 0 || |
| | strcmp(tmp->arch->name, "tree5") == 0 || |
| | strcmp(tmp->arch->name, "woods4") == 0 || |
| | strcmp(tmp->arch->name, "woods5") == 0) { |
| | remove_ob(tmp); |
| | free_object(tmp); |
| | } |
| | break; |
| | } |
| | } |
| | } |
| | } |
| | } |
| | } |
| | |
/* provide wx and wy. Will fill in with weathermap coordinates. Requires | | /* provide wx and wy. Will fill in with weathermap coordinates. Requires |
the current mapname (must be a worldmap), and your coordinates on the | | the current mapname (must be a worldmap), and your coordinates on the |
| | |
spwtx = (settings.worldmaptilesx * settings.worldmaptilesizex) / WEATHERMAPTILESX; | | spwtx = (settings.worldmaptilesx * settings.worldmaptilesizex) / WEATHERMAPTILESX; |
spwty = (settings.worldmaptilesy * settings.worldmaptilesizey) / WEATHERMAPTILESY; | | spwty = (settings.worldmaptilesy * settings.worldmaptilesizey) / WEATHERMAPTILESY; |
| | |
| | while (*filename == '/') |
| | *filename++; |
| | |
fx = -1; | | fx = -1; |
fy = -1; | | fy = -1; |
sscanf(filename, "world/world_%d_%d", &fx, &fy); | | sscanf(filename, "world/world_%d_%d", &fx, &fy); |