/*
 *Snippet Purpose:        swimming skill
 *Release Version:        1.0
 *Snippet Coder:          Icechild
 *Coder E-mail address:   liquidice@usa.net
 *Codebase Designed for:  ROM2.4b6
 *Date of Publication:    March 02, 2001
 *
 *This is my fairly simple, but quite useful swimming skill for all those whom have been asking 
 *for something like it.
 *
 *It uses an UNDERWATER room for when the player drowns, this room can be recallable or not, depending 
 *on your preference.  If you want to add a new dimension to it, I recommend getting the SECT_UNDERWATER
 *snippet, or designing one on your own like I did.  That way people shouldn't stay in this room for 
 *very long :)  I've created the room in Limbo, since well, a lot of OBJ's are used in that area, but 
 *no one ever seems to utilize the rooms :)  And I was sure everyone would have this area (unless you've 
 *moved everything to another area, which I wouldn't see the point of)
 *
 *If you have any questions/concerns/ideas for this code, just write me an e-mail, I'll see if I can't 
 *figure out some more things to do with this :)
 *
 *If you wanna use this code, feel free, the only thing I'd like is a little entry in HELP SWIMMING stating 
 *you used my code (IE: Origional Swimming Code Design by: IceChild (liquidice@usa.net)).
 *
 *I, like most snippet providers, take no responcibility for your actions as a coder.  This code compiled 
 *fine into my mud, and I'm sure it'll work in yours.  But if it messes up your code, I'm sorry, but there 
 *is nothing I can, nor will, do.  Make sure you ALWAYS backup your code before you even attempt to add 
 *anything to your codebase.  If you dont, your only hurting yourself.
 *
 *Please note that this code, while tested, is not overly tested.  I code mainly because I enjoy it, not 
 *because I'm some coder on a popular mud, or anything like that.  So my ability to test it is only limited 
 *to the resources I have available.  But hey, It shouldn't be that bad :)
 *
 *CHANGES: 
 *From 0.5 to 1.0:
 *         Fixed a rather nasty bug where the mud would crash if someone was in a note editor, due to the 
 *         floating piece in update.c  Shouldn't have that problem anymore.
 *
 */

/* Incase you didn't read it before, BACK UP YOUR CODE! NOW! */

/* CONST.C */
// In the skill_table, add:
    {   
        "swimming",             {1, 1, 1, 1}, {2, 2, 2, 2}, 
	spell_null,             TAR_IGNORE,             POS_STANDING,
        &gsn_swimming,          SLOT( 0),       0,      12,
	"",                     "!Swimming!",           ""
    },

/* MERC.H */
// With the rest of the gsn_'s, add:
  extern sh_int gsn_swimming;

// With the rest of the ROOM_VNUM_ defines add: /*This is the room we'll send them to when they drown :) */
  #define ROOM_VNUM_UNDERWATER          3

/* DB.C */
// With the rest of the gsn_'s, add:
  sh_int gsn_swimming;


/* ACT_MOVE.C */
// Function: move_char
//  Just before the SECT_WATER_NOSWIM portion, add this:

/* Uncomment this if you have mounts
	if ( (in_room->sector_type == SECT_WATER_SWIM || to_room->sector_type == SECT_WATER_SWIM ) && MOUNTED(ch))
        {
            sprintf( buf,"You can't take your mount there.\n\r");
            send_to_char(buf, ch);
            return;
        } 
*/

	if(( in_room->sector_type == SECT_WATER_SWIM || to_room->sector_type == SECT_WATER_SWIM ) && !IS_AFFECTED(ch, AFF_SWIM) && !IS_AFFECTED(ch,AFF_FLYING))
	  {
	    OBJ_DATA *obj;
	    bool has_boat;
	    int chance;

	    /*
	     * Look for a boat.
	     */
	    has_boat = FALSE;

	    if (IS_IMMORTAL(ch))
		has_boat = TRUE;

	    for ( obj = ch->carrying; obj != NULL; obj = obj->next_content )
	    {
		if ( obj->item_type == ITEM_BOAT )
		{
		    has_boat = TRUE;
		    break;
		}
	    }
	    if ( !has_boat )
	    {	    
	      if(!IS_NPC(ch) && ch->level < skill_table[gsn_swimming].skill_level[ch->class])
		{
		  send_to_char("You need to learn to swim first",ch);
		  return;
		}

	      if((chance = get_skill(ch,gsn_swimming)) == 0)
		{
		  send_to_char("You dont know how to swim.\n\r",ch);
		  return;
		}

	      if(IS_SET(ch->vuln_flags, VULN_DROWNING))
	        chance /= 2;

	      chance -= ((ch->max_move / ch->move) / 2); /* how rested is the swimmer? */
	      chance -= (get_carry_weight(ch) / 10); /* how heavy is the swimmer? */

	      if(ch->race == race_lookup("dwarf")) /* dwarf's can't swim. */
		{
		  chance = 0;
		}
	      
	      if(number_percent() < chance)
		{
		  check_improve(ch,gsn_swimming,TRUE, 5);
		}
	      else
		{
		  check_improve(ch,gsn_swimming,FALSE, 5);
		  send_to_char("You drown.\n\r",ch);
		  char_from_room(ch);
		  char_to_room(ch, get_room_index(ROOM_VNUM_UNDERWATER));
		  do_look(ch,"auto");
		  if (ch->pet != NULL)
		    {
		      char_from_room( ch->pet );
		      char_to_room( ch->pet, ch->in_room );
		      do_look(ch->pet,"auto");
		    }
/* Again, uncomment if your using mount code 
		  if (ch->mount != NULL)
		    {
		      char_from_room(ch->mount);
		      char_to_room( ch->mount, ch->in_room );
		      do_look(ch->mount,"auto");
		    }
*/
		  return;
		}
	    }
	  }

/* UPDATE.C */
// Function: char_update
//  Any logical place you want add this:
	/* How long can you float :) */
	if(ch->desc && ch->desc->connected == CON_PLAYING)
	  if(!IS_NPC(ch))
	    {
	      if( ch->in_room && (ch->in_room->sector_type == SECT_WATER_SWIM && !IS_AFFECTED(ch,AFF_FLYING)))
		{
		  OBJ_DATA *obj;
		  bool has_boat;
		  int chance;
		  
		  /*
		   * Look for a boat.
		   */
		  has_boat = FALSE;
		  
		  if (IS_IMMORTAL(ch))
		    has_boat = TRUE;
		  
		  for ( obj = ch->carrying; obj != NULL; obj = obj->next_content )
		    {
		      if ( obj->item_type == ITEM_BOAT )
			{
			  has_boat = TRUE;
			  break;
			}
		    }
		  if ( !has_boat )
		    {	    
		      if(!IS_NPC(ch) && ch->level < skill_table[gsn_swimming].skill_level[ch->class])
			{
			  send_to_char("You shouldn't be here, report this to an IMM.\n\r",ch);
			  return;
			}
		      
		      if((chance = get_skill(ch,gsn_swimming)) == 0)
			{
			  send_to_char("You shouldn't be here, report this to an IMM.\n\r",ch);
			  return;
			}
		      
		      if(IS_SET(ch->vuln_flags, VULN_DROWNING))
			chance /= 2;
		      
		      /*chance -= ((ch->max_move / ch->move) / 2); commented cause you can float easily */
		      /*chance -= (get_carry_weight(ch) / 10); again, floating is easier*/
		      
		      if(ch->race == race_lookup("dwarf")) /* dwarf's can't float. */
			{
			  chance = 0;
			}
		      
		      if(number_percent() < chance)
			{
			  check_improve(ch,gsn_swimming,TRUE, 5);
			}
		      else
			{
			  check_improve(ch,gsn_swimming,FALSE, 5);
			  send_to_char("You drown.\n\r",ch);
			  char_from_room(ch);
			  char_to_room(ch, get_room_index(ROOM_VNUM_UNDERWATER));
			  do_look(ch,"auto");
			  if (ch->pet != NULL)
			    {
			      char_from_room( ch->pet );
			      char_to_room( ch->pet, ch->in_room );
			      do_look(ch->pet,"auto");
			    }
			  if (ch->mount != NULL)
			    {
			      char_from_room(ch->mount);
			      char_to_room( ch->mount, ch->in_room );
			      do_look(ch->mount,"auto");
			    }
			  return;
			}
		    }
		}
	    }

/* CONGRADULATIONS! Do a clean compile, and you should be set to go. */