/
area/city/
area/crypts/
area/guilds/
area/psuedowild/
area/religion/
data/documents/MPDocs/
data/html/
data/mobprogs/
data/quest/
data/world/
data/world/_utilities/
data/world/images/
design/html/
notes/
player/
#if defined(macintosh)
#include <types.h>
#include <time.h>
#else
#include <sys/types.h>
#include <sys/time.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "recycle.h"
#include "tables.h"
#include "lookup.h"

/*
 * Functions needed for shapeshifting, which uses cloning
 */
bool obj_check args((CHAR_DATA *ch, OBJ_DATA *obj));
void recursive_clone args((CHAR_DATA *ch, OBJ_DATA *obj, OBJ_DATA *clone));
ROOM_INDEX_DATA *       find_location   args( ( CHAR_DATA *ch, char *arg ) );

/* Finally, the shapeshift function, heavily commented to allow you to
   modify/change it to your liking */

void do_shapeshift( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    CHAR_DATA *clone;
    OBJ_DATA  *obj;
    OBJ_DATA *new_obj;
    char buf[MAX_STRING_LENGTH];
    ROOM_INDEX_DATA *location;
    CHAR_DATA *keeper;
    SHOP_DATA *pShop;

#ifdef DEBUG
        Debug ("do_shapeshift");
#endif

    /* The normal use of shapeshift is to specify the NPC to switch into,
        i.e. "shapeshift homer" to turn yourself into Homer Simpson.
        Used without an argument will return to your normal body. */
    one_argument( argument, arg );
    
    if ( arg[0] == '\0' ) 
    {
    if ( ch->desc == NULL )
      return;

    if ( ch->desc->original == NULL )
    {
      send_to_char( "{RWho do you want to shapeshift into?\n\r{x", ch );
      return;
    }

    send_to_char( 
      "You return to your original form. Type replay to see any missed tells.\n\r", ch );
    act ( "$n shifts into the shape of $N.", ch, NULL, ch->desc->original, TO_ROOM );
    if (ch->prompt != NULL)
    {
      free_string(ch->prompt);
      ch->prompt = NULL;
    }

    /* following lines are for wiznet */
    sprintf(buf,"$N returns from %s.",ch->short_descr);
    wiznet(buf,ch->desc->original,0,WIZ_SWITCHES,WIZ_SECURE,get_trust(ch));

    /* return player to room which NPC is presently in, then execute
       equivalent of do_return code and extract the NPC. */
    victim = ch->desc->character;
    char_from_room( ch->desc->original );
    char_to_room( ch->desc->original, victim->in_room );

    ch->desc->character       = ch->desc->original;
    ch->desc->original        = NULL;
    ch->desc->character->desc = ch->desc; 
    ch->desc                  = NULL;

    extract_char( victim, TRUE );

    return;
    }

    if ( ch->desc == NULL )
    return;

    /* if already shapeshifted, can't shift again */
    if ( ch->desc->original != NULL )
    {
    send_to_char( 
    "{RYou are not familiar enough with your shape to change it again.{x\n\r", ch );
    return;
    }
    
    /* this is a boolean check used to see if the player has the attribute
       required to shapeshift.  You will have to customize this for your
       mud dependent on which players you want to allow to shapeshift */
    if (!(TRUE))
    {
    send_to_char( "{RYou have not yet mastered shapeshifting.\n\r{x", ch );
    return;
    }

    /* can only shapeshift into a NPC that exists */
    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
    send_to_char( "You fail to recognize what to shape yourself into.\n\r", ch );
    return;
    }

    /* players can shapeshift into themselves, no action taken */
    if ( victim == ch )
    {
    send_to_char( "Ok.\n\r", ch );
    return;
    }

    /* otherwise, only NPCs can be used */
    if (!IS_NPC(victim))
    {
    send_to_char("{RYou can only shift into the shape of creatures.{x\n\r",ch);
    return;
    }

    /* this should prevent players from shapeshifting into shopkeepers */
    pShop = NULL;
    for ( keeper = victim->in_room->people; keeper; keeper = keeper->next_in_room )
    {
    if ( IS_NPC(keeper) && (pShop = keeper->pIndexData->pShop) != NULL)
        break;
    }

    if ( pShop != NULL )
    {
       send_to_char("{GYOU WISH!!!!!!!!{x\n\r", ch );
       return;
    }

    /* this should prevent players from shapeshifting into guildmasters, healers,
    money changers, etc. */
    if (IS_SET(victim->act,ACT_TRAIN)
    ||  IS_SET(victim->act,ACT_PRACTICE)
    ||  IS_SET(victim->act,ACT_IS_HEALER)
    ||  IS_SET(victim->act,ACT_IS_CHANGER))
    {
    send_to_char("Don't even think about it!\n\r",ch);
    return;      
    }

    /* level-based restriction */
    if ( victim->level > ch->level )
    {
      act ("{R$N is far too complex for you to shift shapes.{x",
      ch, NULL, victim, TO_CHAR);
      return;
    }

/* OK we've passed all checks for use of the function, let's execute the shift */

/* Step 1, create a clone of the mob the player is shifting into, including eq.*/
    clone = create_mobile(victim->pIndexData);
    clone_mobile(victim,clone);
    
    for (obj = victim->carrying; obj != NULL; obj = obj->next_content)
    {
        if (obj_check(ch,obj))
        {
        new_obj = create_object(obj->pIndexData,0);
        clone_object(obj,new_obj);
        recursive_clone(ch,obj,new_obj);
        obj_to_char(new_obj,clone);
        new_obj->wear_loc = obj->wear_loc;
        }
    }
    char_to_room(clone,ch->in_room);

/* Step 2, switch the player into NPC (clone) body */
    act ( "{RYou shift into the shape of {B$N{x.", ch, NULL, clone, TO_CHAR );
     act ( "{R$n shifts into the shape of {B$N{x.", ch, NULL, clone, TO_ROOM );
    sprintf(buf,"$N shapeshifts into %s",victim->short_descr);
    wiznet(buf,ch,NULL,WIZ_SWITCHES,WIZ_SECURE,get_trust(ch));

    ch->desc->character = clone;
    ch->desc->original  = ch;
    clone->desc         = ch->desc;
    ch->desc            = NULL;
    /* change communications to match */
     if (ch->prompt != NULL)
        clone->prompt = str_dup(ch->prompt);
    clone->comm = ch->comm;
    clone->lines = ch->lines;
/* Step 2a, since switched mob can move around, it might accidentally attack
   newbies.  Let's make it non-aggro */
    REMOVE_BIT(clone->act,ACT_AGGRESSIVE);
/* Step 3, transfer player to holding area.  Substitute "1" with appropriate
   vnum for room you want player to go to (limbo).  If player drops link while
   shapeshifted they will return in that room, so make sure it's recallable. */
    location = find_location( ch, "1" );
    char_from_room(ch);
    char_to_room(ch,location);
    return;
}