/
roa/
roa/lib/boards/
roa/lib/config/
roa/lib/edits/
roa/lib/help/
roa/lib/misc/
roa/lib/plrobjs/
roa/lib/quests/
roa/lib/socials/
roa/lib/www/
roa/lib/www/LEDSign/
roa/lib/www/LEDSign/fonts/
roa/lib/www/LEDSign/scripts/
roa/src/s_inc/
roa/src/sclient/
roa/src/sclient/binary/
roa/src/sclient/text/
roa/src/util/
/************************************************************************
	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 */