From: ferric@white116.uwyo.edu ------------------------------------------------------------------------- Ok, this code is for a morph skill I added to my mud; it basically lets a player mimic an object of their level or lower, anywhere in the game world. It has the following restrictions: -You cannot save, cast, or fight while morphed. -You are still a player, so can't use object commands on a morphed player. -At auto-save you are forced to reform (to avoid odd pfile names). -When morphed, you are not parsed in as a true object is. This is because I didn't want morph to stand up under careful inspection. Now, this code is easily configurable for however you want it to work on your mud. If you find bugs, or need help with this code, contact Ferric@uwyo.edu. I realize this code could have been simplified, or made more elaborate; feel free to make alterations as you see fit. I treat it as a command for thieves/mages on my mud. Perhaps a spell would have made more sense, but I like this. Enjoy; feel free to drop me a line at ferric@uwyo.edu if you use this code. ---------------------------------------------------------------------------- ----------- First: ----------- At the top of: act_comm.c, fight.c, magic.c, save.c, add: void do_reform args( (CHAR_DATA *ch) ); ---------- Next: Merc.h ---------- In merc.h find #define COMM_AFK. Under it add: #define COMM_MORPH (bb) /*I used Comm because it was open, and you can use any open flags instead of bb.*/ --------- then: merc.h --------- find: extern sh_int gsn_enhance; and under it add: extern sh_int gsn_morph; --------- then: merc.h --------- /*This is ugly code, and could be done nicer. But, it works! :) -Ferric*/ Find: char * name; /*in struct char_data*/ and char * description;/*same place*/ and add below each (respectively): char * backup_name; char * backup_desc; -------- then: merc.h -------- In struct pc_data find: char * title; add below it: char * backup_title; -------- Next: act_info.c -------- Add the following bits of code. I used act_info.c for no real reason, but you may as well add it there. void do_reform(CHAR_DATA *ch) { /*This code is used to retake your shape. -Ferric*. if(IS_NPC(ch)) return; if(!IS_SET(ch->comm,COMM_MORPH)) { send_to_char("You are in your origional shape.\n\r",ch); return; } REMOVE_BIT(ch->comm,COMM_MORPH); ch->name = ch->backup_name; ch->pcdata->title = ch->pcdata->backup_title; ch->description = ch->backup_desc; act("$n regains $s real shape.\n\r",ch,NULL,NULL,TO_ROOM); send_to_char("You retake your familiar shape.\n\r",ch); } void do_polymorph(CHAR_DATA *ch, char *argument ) { OBJ_DATA *obj; int number = 0, max_found; int skill; number = 0; max_found = 200; if(IS_NPC(ch)) return; if ((skill = get_skill(ch,gsn_morph)) < 1) { send_to_char("You are unable to morph!\n\r",ch); return; } smash_tilde(argument); if (argument[0] == '\0') { send_to_char("Polymorph into what?\n\r",ch); return; } if(IS_SET(ch->comm,COMM_MORPH)) { send_to_char("You must wait until you regain your shape.\n\r",ch); return; } /*Don't ask me why I duplicated this code. But since it's already here, I'll leave it. Shouldn't be a prob if you cut the next 3 lines. -Ferric */ ch->backup_name = ch->name; ch->pcdata->backup_title= ch->pcdata->title; ch->backup_desc = ch->description; for ( obj = object_list; obj != NULL; obj = obj->next ) { if ( !can_see_obj( ch, obj ) || !is_name( argument, obj->name ) || ch->level < obj->level) continue; act("$n morphs into $p",ch,obj,NULL,TO_ROOM); ch->backup_name = ch->name; ch->pcdata->backup_title= ch->pcdata->title; ch->backup_desc = ch->description; SET_BIT(ch->comm,COMM_MORPH); ch->pcdata->title = (""); ch->name = obj->description; ch->description = obj->description; send_to_char("You have changed!\n\r",ch); return; } /*Failure. -Ferric*/ send_to_char("Try as you might, you cannot.\n\r",ch); } -------- Next: act_info.c -------- /* Ok: We don't want odd who's and whois's. So: I added this check. */ In do_whois, find the line: IS_SET(wch->act,PLR_THIEF) ? "(THIEF) " : "", Under it add: IS_SET(wch->comm,COMM_MORPH) ? wch->backup_name:wch->name, IS_NPC(wch) ? "" : IS_SET(wch->comm,COMM_MORPH) ? wch->pcdata->backup_title: wch->pcdata->title); /*The NPC check probably doesn't matter, but doesn't hurt anything.*/ --------- then: act_info.c --------- In do_who, find the line: IS_SET(wch->act,PLR_THIEF) ? "(THIEF) " : "", Under it add: IS_SET(wch->comm,COMM_MORPH) ? wch->backup_name:wch->name, IS_NPC(wch) ? "" : IS_SET(wch->comm,COMM_MORPH) ? wch->pcdata->backup_title: wch->pcdata->title); /*The NPC check probably doesn't matter, but doesn't hurt anything.*/ ----------- then: act_info.c ----------- In show_char_to_char find: char buf[MAX_STRING_LENGTH],message[MAX_STRING_LENGTH], under it add: buf2[MAX_STRING_LENGTH]; then find (still in show_char_to_char) strcat( buf, PERS( victim, ch ) ); if ( !IS_NPC(victim) && !IS_SET(ch->comm, COMM_BRIEF) && victim->position == POS_STANDING && ch->on == NULL ) strcat( buf, victim->pcdata->title ); Directly under it add: /* This allows immortals to see the real identity of morphed chars who are in the same room. */ if(IS_SET(victim->comm,COMM_MORPH) && IS_IMMORTAL(ch)) { sprintf(buf2, " [%s] ",victim->backup_name); strcat( buf,buf2); } ---------- then: act_info.c ---------- find: switch ( victim->position ) { case POS_DEAD: strcat( buf, " is DEAD!!" ); break; case POS_MORTAL: strcat( buf, " is mortally wounded." ); break; case POS_INCAP: strcat( buf, " is incapacitated." ); break; case POS_STUNNED: strcat( buf, " is lying here stunned." ); break; case POS_SLEEPING: change to: /* This prevents wounded morphed chars from giving it away.*/ if(!IS_SET(victim->comm,COMM_MORPH)) switch ( victim->position ) { case POS_DEAD: strcat( buf, " is DEAD!!" ); break; case POS_MORTAL: strcat( buf, " is mortally wounded." ); break; case POS_INCAP: strcat( buf, " is incapacitated." ); break; case POS_STUNNED: strcat( buf, " is lying here stunned." ); break; case POS_SLEEPING: ---------- Next: const.c ---------- Add this in the skill table in const.c /*Change this to suit your mud. -Ferric*/ /*Be sure to add it to any defaults you want, as well.*/ { "morph", { 28, 63, 15, 63}, { 5, 0, 7, 0}, spell_null, TAR_CHAR_SELF, POS_RESTING, &gsn_morph, SLOT(0), 0, 12, "morph", "!Morph!", "" }, /* Now we get to add all the nifty checks for things that don't allow players to do while morphed. Feel free to change any, but take my advice and don't allow players to save while morphed unless you add a function to have it save to their origional name. -Ferric */ --------- Next: act_comm.c --------- in do_delete, under the: if (IS_NPC(ch)) return; add: if(IS_SET(ch->comm,COMM_MORPH)) do_reform(ch); --------- then: act_comm.c --------- in do_quit find: if ( IS_NPC(ch) ) return; and under it add: if(IS_SET(ch->comm,COMM_MORPH)) do_reform(ch); /*probably not necissary with the check in do_save, but doesn't hurt.*. ----------- then: act_comm.c ----------- find: do_save under it add: if(IS_SET(ch->comm,COMM_MORPH)) do_reform(ch); -------- Next: fight.c -------- in function one_hit find: if ( victim->position == POS_DEAD || ch->in_room != victim->in_room ) return; under it add: if(IS_SET(ch->comm,COMM_MORPH)) do_reform(ch); ---------- Next: magic.c ---------- in do_cast, find if ( IS_NPC(ch) && ch->desc == NULL) return; under it add: if(IS_SET(ch->comm,COMM_MORPH)) do_reform(ch); ---------- Next: save.c ---------- /*I know this isn't needed, per se, but I'm using it as a 'safety latch', should anybody get past the previous ones. I can't stress enough how importanat it is to prevent the saving of morphed chars.*/ find save_char_obj; in it find: if ( IS_NPC(ch) ) return; under it add: if(IS_SET(ch->comm,COMM_MORPH)) do_reform(ch); ------- Lastly: interp.c and interp.h ------- In interp.c add: { "reform", do_reform, POS_RESTING, 0, LOG_NORMAL, 1}, { "morph", do_polymorph, POS_RESTING, 0, LOG_ALWAYS, 1}, /*Still deciding if it can be abused.*/ in interp.h add: DECLARE_DO_FUN( do_polymorph ); DECLARE_DO_FUN( do_reform ); ------------ Done! ------------ Ok, as I've said, this code could certainly used a clean-up. Basically I wrote it, and when it worked, I never looked back. And if you should find any bugs in this, *please* email me with them so that I can fix them up and re-release this code. Last thing; you needn't credit me in any way you don't want to, although an email to ferric@uwyo.edu letting me know you are using it will certainly be appreciated, and might even encourage me to release some more of my more interesting code. ----------- Note ----------- If you are using mahntor.are, obj #1336 (a golden altar) has no description; so, any player morphing into it is effectivly super-invis. A couple of fixes: either add a description, or up the level high enough that it's impossible for anybody to morph into it. ------------ To-do list ------------ -change 'where' to be more accurate with this. -allow a more efficient way for imms to see morphed chars. -clean the code up a great deal. -parse the name in so that it matches up w/ other objects. -allow for (glowing) (humming) flags on chars morphed to appropriate objects. -fix tell so that you can tell to morphed players w/out knowing their current shape. So, thanks for your time/attention, and happy mudding/Admining. -Ferric ferric@uwyo.edu white116.uwyo.edu 9000