/************************************************************************ Realms of Aurealis James Rhone aka Vall of RoA nature.c RoA environment and nature code is found in this file, with the exception of most weather stuff, which is found... where else, but weather.c :) Deals with the floating/sinking/blowing actions of objects and players as they encounter them within the everyday environment. Things like wind, water, and air as they relate to players can be found in this file. ******** Heavily modified and expanded ******** *** BE AWARE OF ALL RIGHTS AND RESERVATIONS *** ******** Heavily modified and expanded ******** All rights reserved henceforth. Please note that no guarantees are associated with any code from Realms of Aurealis. All code which has been released to the general public has been done so with an 'as is' pretense. RoA is based on both Diku and CircleMUD and ALL licenses from both *MUST* be adhered to as well as the RoA license. *** Read, Learn, Understand, Improve *** *************************************************************************/ #include "conf.h" #include "sysdep.h" #include "structures.h" #include "utils.h" #include "comm.h" #include "interpreter.h" #include "handler.h" #include "db.h" #include "screen.h" #include "mudlimits.h" #include "fight.h" #include "affect.h" #include "lists.h" #include "global.h" /* extern variables */ extern char *rev_dir_str[]; extern char *dirs[]; // external functions extern int check_room_affects(chdata *ch, int room); /************** Stuff for FLOATING and SINKING and all that garbage that goes with AIR and UWATER rooms..... RoA Innovations...James Rhone ***************/ #define HAS_DROPTO(r) (world[(r)].terrain_type == TERRAIN_AIR ||\ world[(r)].terrain_type == TERRAIN_UWATER ||\ world[(r)].terrain_type == TERRAIN_WATER_NOSWIM ||\ world[(r)].terrain_type == TERRAIN_WATER_SWIM) #define HAS_WATER(r) (world[(r)].terrain_type == TERRAIN_UWATER ||\ world[(r)].terrain_type == TERRAIN_WATER_NOSWIM ||\ world[(r)].terrain_type == TERRAIN_WATER_SWIM) /* FOR UWATER AND AIR ROOMS GOLD WILL PLUMMET RoA Innovations James Rhone */ void float_sink_gold(obdata *obj, int room) { int drop, newroom; int count = 0; if (INVALID_ROOM(room)) { sprintf(buf, "SYSERR: f_sink_gold invalid room #%d, %s", GET_OBJ_VNUM(obj), obj->shdesc); mudlog(buf, BRF, LEV_IMM, TRUE); return; } newroom = room; drop = world[newroom].drop_to; while (HAS_DROPTO(newroom) && drop > 0 && real_room(drop) > 0) { if (HAS_WATER(newroom)) { sprintf(buf, "The %s sinks!", currency_name); sprintf(buf2, "Some %s have sunk down from above!", currency_name_plural); } else { sprintf(buf, "The %s drops through the air!", currency_name); sprintf(buf2, "Some %s have fallen from above!", currency_name_plural); } send_to_room_not_busy(buf, newroom); send_to_room_not_busy(buf2, real_room(drop)); newroom = real_room(drop); drop = world[newroom].drop_to; count++;if (count >= 15) break; /* loop check */ } obj_to_room(obj, newroom); } /* FOR UWATER AND AIR ROOMS OBJECTS MAY FLOAT OR SINK RoA Innovations James Rhone */ void float_sink_object(obdata *obj, int room) { int drop, newroom, rise; int count = 0; if (INVALID_ROOM(room)) { sprintf(buf, "SYSERR: f_sink_obj invalid room #%d, %s", GET_OBJ_VNUM(obj), obj->shdesc); mudlog(buf, BRF, LEV_IMM, TRUE); return; } newroom = room; drop = world[newroom].drop_to; rise = world[newroom].float_to; if (world[newroom].terrain_type == TERRAIN_AIR) { while (world[newroom].terrain_type == TERRAIN_AIR && drop > 0 && real_room(drop) > 0) { sprintf(buf, "%s drops through the air!", obj->shdesc); sprintf(buf2, "%s has fallen from above!",obj->shdesc); CCAP(buf); CCAP(buf2); send_to_room_not_busy(buf, newroom); send_to_room_not_busy(buf2, real_room(drop)); newroom = real_room(drop); drop = world[newroom].drop_to; count++;if (count >= 15) break; } } else if (HAS_WATER(newroom)) { if (!OBJ_FLAGGED(obj, ITEM_BOUYANT)) { while (HAS_WATER(newroom) && drop > 0 && real_room(drop) > 0) { sprintf(buf, "%s sinks below!", obj->shdesc); sprintf(buf2, "%s comes sinking from above!",obj->shdesc); CCAP(buf); CCAP(buf2); send_to_room_not_busy(buf, newroom); send_to_room_not_busy(buf2, real_room(drop)); newroom = real_room(drop); drop = world[newroom].drop_to; count++;if (count >= 15) break; } } else while (world[newroom].terrain_type == TERRAIN_UWATER && rise > 0 && real_room(rise) > 0) { sprintf(buf, "%s floats up!", obj->shdesc); sprintf(buf2, "%s floats here from below!",obj->shdesc); CCAP(buf); CCAP(buf2); send_to_room_not_busy(buf, newroom); send_to_room_not_busy(buf2, real_room(rise)); newroom = real_room(rise); rise = world[newroom].float_to; count++;if (count >= 15) break; } } obj_to_room(obj, newroom); } /* FOR UWATER AND AIR ROOMS CHARACTERS may float or sink if their AFF runs out while in mid air or underwater RoA Innovations James Rhone */ int float_sink_char(chdata *ch) { int drop, newroom, rise; int count = 0; if (INVALID_ROOM(ch->in_room)) { sprintf(buf, "SYSERR: float_sink_char invalid room (%s)", GET_NAME(ch)); mudlog(buf, BRF, LEV_IMM, TRUE); return CHAR_OK; } newroom = ch->in_room; drop = world[newroom].drop_to; rise = world[newroom].float_to; if ((world[newroom].terrain_type == TERRAIN_AIR) && !IS_FLYING(ch)) { while (world[newroom].terrain_type == TERRAIN_AIR && !IS_FLYING(ch) && drop > 0 && real_room(drop) > 0) { act("$n falls through the air!", TRUE, ch, 0, 0, TO_ROOM); char_from_room(ch); char_to_room(ch, real_room(drop)); if (check_room_affects(ch, ch->in_room) == CHAR_DIED) return CHAR_DIED; if (check_death_trap(ch, NULL)) return CHAR_DIED; act("$n has fallen from above!", TRUE, ch, 0, 0, TO_ROOM); send_to_char("You are FALLING!!\n\r", ch); newroom = real_room(drop); drop = world[newroom].drop_to; count++;if (count >= 15) break; } } else if (HAS_WATER(newroom) && !IS_AFFECTED(ch, AFF_GILLS)) { while ((world[newroom].terrain_type == TERRAIN_UWATER) && !IS_AFFECTED(ch, AFF_GILLS) && rise > 0 && real_room(rise) > 0) { act("$n runs out of air and starts to swim up!", TRUE, ch, 0, 0, TO_ROOM); char_from_room(ch); char_to_room(ch, real_room(rise)); if (check_room_affects(ch, ch->in_room) == CHAR_DIED) return CHAR_DIED; if (check_death_trap(ch, NULL)) return CHAR_DIED; send_to_char("Your gills have disappeared, you struggle to find air!!\n\r", ch); act("$n swims up from below, gasping for air!", TRUE, ch, 0, 0, TO_ROOM); newroom = real_room(rise); rise = world[newroom].float_to; count++;if (count >= 15) break; } } /* do the damage calc here, ... */ return CHAR_OK; } /* for WINDY and UWATER rooms, drifting and blowing stuff RoA innovations */ void do_room_wind(int i) { obdata *obj; int j, dir, zone; BOOL found = FALSE; int rroom; zone = world[i].zone; if (!ZONE_FLAGGED(zone, Z_CLOSED) && !ZONE_FLAGGED(zone, Z_LOCKED)) { if (ROOM_FLAGGED(i, WINDY) && (world[i].drift_to > 0)) { if ((rroom = real_room(world[i].drift_to)) > 0) { if (number(0,1)) /* send wind message half the time */ { switch(number(0,4)) { case 0: sprintf(buf,"A light breeze cools you off."); break; case 1: sprintf(buf,"A gust of wind touches your face."); break; case 2: sprintf(buf,"Wind echos in your ears."); break; default: sprintf(buf,"A cold wind rages against you."); break; } send_to_room_not_busy(buf, i); } else for (obj = world[i].contents; obj; obj = obj->next_content) if (GET_OBJ_WEIGHT(obj) <= 2 && !OBJ_FLAGGED(obj, ITEM_ANCHORED)) { sprintf(buf, "%s is caught by the wind and blows away.", obj->shdesc); CCAP(buf); send_to_room_not_busy(buf, i); sprintf(buf, "%s has been blown here by the wind.", obj->shdesc); CCAP(buf); send_to_room_not_busy(buf, rroom); obj_from_room(obj); float_sink_object(obj, rroom); break; } } /* end of non random dir */ else if (world[i].drift_to == 0) /* a random direction */ { for (j=0, found = FALSE; j < 10; j++) { dir = number(0, 9); if (world[i].dir_option[dir]) { found = TRUE; break; } } if (number(0,1) && found) /* send wind message half the time */ { switch(number(0,4)) { case 0: sprintf(buf,"A light breeze from %s cools you off.", rev_dir_str[dir]); break; case 1: sprintf(buf,"A gust of wind from %s touches your face.", rev_dir_str[dir]); break; case 2: sprintf(buf,"Wind from %s echos in your ears.", rev_dir_str[dir]); break; default: sprintf(buf,"A cold wind rages against you from %s.", rev_dir_str[dir]); break; } send_to_room_not_busy(buf, i); } else if (found) for (obj = world[i].contents; obj; obj = obj->next_content) if (GET_OBJ_WEIGHT(obj) <= 2 && !OBJ_FLAGGED(obj, ITEM_ANCHORED)) { sprintf(buf, "%s is caught by the wind and blows %s.", obj->shdesc, dirs[dir]); CCAP(buf); send_to_room_not_busy(buf, i); sprintf(buf, "The wind has blown %s here from the %s.", obj->shdesc, dirs[dir]); send_to_room_not_busy(buf, world[i].dir_option[dir]->to_room); obj_from_room(obj); float_sink_object(obj, world[i].dir_option[dir]->to_room); break; } } /* end of else its a random dir */ } /* if windy */ } /* if not closed or locked */ } void pick_wawa_str(char *buf) { switch(number(0,4)) { case 0: sprintf(buf,"The current here lightly drags against you."); break; case 1: sprintf(buf,"You feel the light force of the current."); break; case 2: sprintf(buf,"Moderate current pushes against you."); break; default: sprintf(buf,"The swift current forces you to regain your balance."); break; } } /* do that underwater drifting around thinger RoA*/ void do_room_drift(int i) { obdata *obj; int j, dir, zone; BOOL found = FALSE; zone = world[i].zone; if (!ZONE_FLAGGED(zone, Z_CLOSED) && !ZONE_FLAGGED(zone, Z_LOCKED)) { if (HAS_WATER(i) && world[i].drift_to > 0) { if (real_room(world[i].drift_to) > 0) { if (number(0,1)) /* send wind message half the time */ { pick_wawa_str(buf); send_to_room_not_busy(buf, i); } else for (obj = world[i].contents; obj; obj = obj->next_content) { if (!OBJ_FLAGGED(obj, ITEM_ANCHORED)) { sprintf(buf, "%s is caught by the current and drifts away.", obj->shdesc); CCAP(buf); send_to_room_not_busy(buf, i); sprintf(buf, "%s has drifted here.\n\r", obj->shdesc); CCAP(buf); send_to_room_not_busy(buf, real_room(world[i].drift_to)); obj_from_room(obj); float_sink_object(obj, real_room(world[i].drift_to)); break; } } } else if (world[i].drift_to == 0) /* a random direction */ { for (j=0, found = FALSE; j < 10; j++) { dir = number(0, 9); if (world[i].dir_option[dir]) { found = TRUE; break; } } if (number(0,1) && found) /* send wind message half the time */ { switch(number(0,4)) { case 0: sprintf(buf,"A light current from %s gently sways you.", rev_dir_str[dir]); break; case 1: sprintf(buf,"A slight current from %s pushes against you.", rev_dir_str[dir]); break; case 2: sprintf(buf,"A light rush of water from %s presses against you.", rev_dir_str[dir]); break; default: sprintf(buf,"A strong current from %s nearly knocks you over.", rev_dir_str[dir]); break; } send_to_room_not_busy(buf, i); } else if (found) for (obj = world[i].contents; obj; obj = obj->next_content) { if (!OBJ_FLAGGED(obj, ITEM_ANCHORED)) { sprintf(buf, "%s is caught by the current and drifts %s.", obj->shdesc, dirs[dir]); CCAP(buf); send_to_room_not_busy(buf, i); sprintf(buf, "The current has caused %s to drift here from the %s.", obj->shdesc, dirs[dir]); send_to_room_not_busy(buf, world[i].dir_option[dir]->to_room); obj_from_room(obj); float_sink_object(obj, world[i].dir_option[dir]->to_room); break; } } } } } } /* end of proc */