Here is my version of house code. I know some of the things in it could be better, but this is a pretty good starting point. I chose to put the objects and mobs into a table for easier expansion. Make sure to create a new area for this, I suggest making it at least 1000 vnums because each persons home takes up 5 rooms. Simply set vnum start, to the first vnum of the area, and vnum stop as the last vnum of the area. Do not build any rooms in this area, the code will do that for the player when they buy the house. And the players will be able to set their own names and descriptions for their rooms. It should be self explanatory, but if you have any problems let me know. This was coded for a rot mud, but other than the ch->platinum it should drop right into a rom mud. You will need olc in order for this code to work, and you must have redit delete. I don't require any credit for using this code, but if you do happen to make some improvements then please send them to me at Synch23@titan.kyndig.com. /*changes in merc.h*/ Put this somewhere in merc.h probably with the other structures struct house_item { char *name; int cost; int vnum; int type; }; Below: extern const struct wiznet_type wiznet_table []; Put this: extern const struct house_item house_table []; Below: #define IS_AWAKE(ch) (ch->position > POS_SLEEPING) Put this: #define HAS_HOME(ch) (!IS_NPC(ch) && ch->pcdata->h_vnum != 0 ) #define IS_HOME(ch) ( ( ch->pcdata->h_vnum != 0 && (ch->in_room->vnum >= ch->pcdata->h_vnum) && (ch->in_room->vnum < ch->pcdata->h_vnum + 5 ) ) ) /* Now I know using the first vnum of a players home is not the best way to handle this, it's kind of limiting, but it seemed easiest at the time. You might want to spend a little time and improve this. */ /* add these variables to struct pc_data */ int h_vnum; int hinvite; sh_int horesets; sh_int hmresets; bool hchange; I think that's it for merc.h. If I left out anything let me know. Now open up special.c Add this at the end of the other spec_fun's: DECLARE_SPEC_FUN( spec_architect ); add this to the end of the spec_fun table: { "spec_architect", spec_architect }, and at the end of the file add this: bool spec_architect(CHAR_DATA * ch) { if (ch->fighting != NULL) return spec_cast_mage(ch); return FALSE; } At the end of tables.h put this: /* vnum types */ #define OBJ_VNUM 1 #define MOB_VNUM 2 At the end of tables.c put this: /* Now obviously here you are going to want to create your own mobs and objects and set the vnum's in the table to match them. If it's an object make it obj_vnum, and if it's a mob make it mob_vnum. */ const struct house_item house_table [] = { /* Name */ /* Cost */ /* Vnum */ /* Type */ { "Couch", 200, 20706, OBJ_VNUM }, { "Healer", 500, 20701, MOB_VNUM }, { NULL, 0, 0, 0, } }; in file interp.h add this to the end: DECLARE_DO_FUN( do_house ); DECLARE_DO_FUN( do_objbuy ); DECLARE_DO_FUN( do_mobbuy ); DECLARE_DO_FUN( do_invite ); DECLARE_DO_FUN( do_home ); DECLARE_DO_FUN( do_hname ); DECLARE_DO_FUN( do_hdesc ); DECLARE_DO_FUN( do_join ); DECLARE_DO_FUN( do_boot ); in file interp.c add this: /* House commands */ { "house", do_house, POS_RESTING, 0, 1, LOG_NORMAL, 1 }, { "objbuy", do_objbuy, POS_RESTING, 0, 1, LOG_NORMAL, 1 }, { "mobbuy", do_mobbuy, POS_RESTING, 0, 1, LOG_NORMAL, 1 }, { "hdesc", do_hdesc, POS_RESTING, 0, 1, LOG_NORMAL, 1 }, { "invite", do_invite, POS_RESTING, 0, 1, LOG_NORMAL, 1 }, { "home", do_home, POS_RESTING, 0, 1, LOG_NORMAL, 1 }, { "join", do_join, POS_RESTING, 0, 1, LOG_NORMAL, 1 }, { "hname", do_hname, POS_RESTING, 0, 1, LOG_NORMAL, 1 }, { "boot", do_boot, POS_RESTING, 0, 1, LOG_NORMAL, 1 }, /* If you are a rot mud, or you have multiclassing you might want to remember to make it so that a players h_vnum carries over through a reroll. */ Changes for db.c in void clear_char below: ch->max_move = 100; add: ch->pcdata->h_vnum = 0; ch->pcdata->horesets = 0; ch->pcdata->hmresets = 0; changes for save.c in function fwrite_char below clans: ( or something similar it can go anywhere in fwrite char basically ) if (ch->clan) { fprintf( fp, "Clan %s~\n",clan_table[ch->clan].name); if (ch->clead) fprintf( fp, "Clead %s~\n",clan_table[ch->clan].name); } add: if( ch->pcdata->h_vnum ) fprintf(fp,"HVnum %d\n", ch->pcdata->h_vnum); if( ch->pcdata->horesets ) fprintf(fp,"HOResets %d\n", ch->pcdata->horesets); if( ch->pcdata->hmresets ) fprintf(fp,"HMResets %d\n", ch->pcdata->hmresets); ok now in fread char below: KEY( "Hit", ch->hitroll, fread_number( fp ) ); add: KEY( "HVnum", ch->pcdata->h_vnum, fread_number( fp ) ); KEY( "HResets", ch->pcdata->horesets, fread_number( fp ) ); KEY( "HOResets", ch->pcdata->horesets, fread_number( fp ) ); KEY( "HMResets", ch->pcdata->hmresets, fread_number( fp ) ); /*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ /*************************************************************************** * ROM 2.4 is copyright 1993-1995 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@pacinfo.com) * * Gabrielle Taylor (gtaylor@pacinfo.com) * * Brian Moore (rom@rom.efn.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * ***************************************************************************/ /*************************************************************************** * ROT 1.4 is copyright 1996-1997 by Russ Walsh * * By using this code, you have agreed to follow the terms of the * * ROT license, in the file doc/rot.license * ***************************************************************************/ #if defined( macintosh ) #include #else #include #endif #include #include #include #include #include "merc.h" #include "tables.h" bool change_exit args( ( CHAR_DATA *ch, char *argument, int door ) ); void edit_done (CHAR_DATA *ch, char *argument ); void save_area (AREA_DATA *pArea ); void home_sell ( CHAR_DATA *ch, int cost ); CHAR_DATA * find_architect args( ( CHAR_DATA * ch ) ); #define MAX_HORESET 5 #define MAX_HMRESETS 5 DECLARE_DO_FUN( do_asave ); DECLARE_DO_FUN( do_redit ); DECLARE_DO_FUN( redit_name ); DECLARE_DO_FUN( redit_desc ); DECLARE_DO_FUN( redit_oreset ); DECLARE_DO_FUN( oedit_create ); DECLARE_DO_FUN( oedit_copy ); DECLARE_DO_FUN( medit_create ); DECLARE_DO_FUN( medit_copy ); DECLARE_DO_FUN( redit_mreset ); DECLARE_DO_FUN( do_look ); DECLARE_DO_FUN( redit_delete ); DECLARE_DO_FUN( do_recall ); #define VNUM_START 20701 #define VNUM_STOP 22699 CHAR_DATA * find_architect ( CHAR_DATA *ch ) { CHAR_DATA * architect; for ( architect = ch->in_room->people; architect != NULL; architect = architect->next_in_room ) { if (!IS_NPC(architect)) continue; if (architect->spec_fun == spec_lookup( "spec_architect" ) ) return architect; } if ( architect == NULL || architect->spec_fun != spec_lookup( "spec_architect" )) { send_to_char("You can't do that here, find an Architect.\n\r", ch); return NULL; } if ( architect->fighting != NULL ) { send_to_char("Wait until the fighting stops.\n\r",ch ); return NULL; } return NULL; } void do_objbuy(CHAR_DATA *ch, char *argument) { char arg[MSL]; char arg1[MSL]; char buf[MSL]; OBJ_DATA *obj; int i; argument = one_argument( argument, arg ); argument = one_argument( argument, arg1 ); if ( !HAS_HOME( ch ) ) { send_to_char("If you only had a home...\n\r",ch); return; } if ( !IS_HOME( ch ) ) { send_to_char("You gotta be in your house.\n\r",ch); return; } if (arg[0] == '\0') { send_to_char("Syntax: objbuy \n\rSyntax: objbuy buy ",ch); return; } if (!str_cmp(arg,"list")) { send_to_char("The following objects are available for purchase:\n\r",ch); send_to_char("{cCost: Name:{x\n\r", ch ); for ( i = 0; house_table[i].name != NULL; i++ ) { if ( house_table[i].type != OBJ_VNUM ) continue; printf_to_char( ch, "%-5d %-10s\n\r", house_table[i].cost, house_table[i].name ); } return; } if (!str_cmp(arg, "buy")) { if (arg1[0] == '\0') { send_to_char( "To buy an item type objbuy buy .\n\r",ch ); return; } for (i = 0; house_table[i].name != NULL; i++) { if (is_name(arg1, house_table[i].name) && house_table[i].type == OBJ_VNUM) { if (ch->platinum >= house_table[i].cost) { if ( (obj = create_object(get_obj_index(house_table[i].vnum), ch->level ) ) == NULL ) { send_to_char( "That object could not be found contact an imm.\n\r", ch ); return; } if( ch->pcdata->horesets > MAX_HORESET ) { send_to_char("Sorry you can only have 5 resetting objects.\n\r",ch); return; } ch->pcdata->horesets++; ch->platinum -= house_table[i].cost; sprintf(buf,"%d", house_table[i].vnum); redit_oreset(ch,buf); sprintf(buf," "); save_area(ch->in_room->area); return; } else { printf_to_char( ch, "Sorry %s but you need %d platinum for that.\n\r", ch->name, house_table[i].cost ); return; } } } } send_to_char( "To buy an item type objbuy buy .\n\r",ch ); return; } void do_mobbuy(CHAR_DATA *ch, char *argument) { char arg[MSL]; char arg1[MSL]; CHAR_DATA *mob; char buf[MSL]; int i; argument = one_argument( argument, arg ); argument = one_argument( argument, arg1 ); if ( !HAS_HOME( ch ) ) { send_to_char("If you only had a home...\n\r",ch); return; } if ( !IS_HOME( ch ) ) { send_to_char("You gotta be in your house.\n\r",ch); return; } if (arg[0] == '\0') { send_to_char("Syntax: mobbuy \n\rSyntax: mobbuy buy ",ch); return; } if (!str_cmp(arg,"list")) { send_to_char("The following mobiles are available for purchase:\n\r",ch); send_to_char("{cCost: Name:{x\n\r\n\r", ch ); for ( i = 0; house_table[i].name != NULL; i++ ) { if ( house_table[i].type != MOB_VNUM ) continue; printf_to_char( ch, "%-5d %-10s\n\r", house_table[i].cost, house_table[i].name ); } return; } if (!str_cmp(arg, "buy")) { if (arg1[0] == '\0') { send_to_char( "To buy an item type mobbuy buy .\n\r",ch ); return; } for (i = 0; house_table[i].name != NULL; i++) { if (is_name(arg1, house_table[i].name) && house_table[i].type == MOB_VNUM) { if (ch->platinum >= house_table[i].cost) { mob = create_mobile(get_mob_index(house_table[i].vnum) ); if ( mob == NULL ) { send_to_char( "That mob could not be found contact an imm.\n\r", ch ); return; } if( ch->pcdata->hmresets > MAX_HMRESETS ) { send_to_char("Sorry you can only have 5 resetting mobiles.\n\r",ch); return; } ch->pcdata->hmresets++; ch->platinum -= house_table[i].cost; sprintf(buf,"%d", house_table[i].vnum); redit_mreset(ch,buf); sprintf(buf," "); save_area(ch->in_room->area); return; } else { printf_to_char( ch, "Sorry %s but you need %d platinum for a %s.\n\r", ch->name, house_table[i].cost, house_table[i].name ); return; } } } } send_to_char("Syntax: mobbuy \n\rSyntax: mobbuy buy ",ch); return; } void do_house( CHAR_DATA *ch, char *argument ) { CHAR_DATA *architect; char arg[MIL]; int osec; char buf[MSL]; int i,i2; int cost = 100000; architect = find_architect( ch ); if (!architect) return; argument = one_argument( argument, arg ); if (IS_NPC(ch)) { send_to_char("Sorry, you'll have to just wander, mobile.\n\r",ch); return; } if ( arg[0] == '\0' && HAS_HOME( ch ) ) { send_to_char( "You already bought a house. To sell it type house .\n\r", ch ); return; } if ( !str_cmp( arg, "sell" ) && HAS_HOME( ch ) ) { home_sell( ch, cost ); return; } if ( HAS_HOME( ch ) ) { send_to_char( "You already own a house. To sell it type house .\n\r", ch ); return; } if (ch->platinum < cost) { printf_to_char( ch, "I'm sorry but it cost %d platinum to buy a house.\n\r", cost ); return; } i = VNUM_START; while (get_room_index(i) != NULL) { i++; if (i > VNUM_STOP - 5) { send_to_char("Sorry all of the house vnums are used up! Tell an immortal.\n\r", ch ); return; } } send_to_char("Okay... Attempting creation of your home.\n\r\n\r",ch); ch->platinum -= cost; osec = ch->pcdata->security; ch->pcdata->security = 5; for (i2 = 4;i2 >= 0;i2--) { sprintf(buf,"create %d",i+i2); do_redit(ch,buf); sprintf(buf,"%s's Home",ch->name); redit_name(ch,buf); } /* * Link the rooms together * 3 * | * 2--1--4 * | * 5 */ sprintf(buf,"link %d",i+1); change_exit(ch,buf,DIR_WEST); sprintf(buf,"link %d",i+2); change_exit(ch,buf,DIR_NORTH); sprintf(buf,"link %d",i+3); change_exit(ch,buf,DIR_EAST); sprintf(buf,"link %d",i+4); change_exit(ch,buf,DIR_SOUTH); ch->pcdata->security = osec; send_to_char("\n\rHURRAY! Your house was made successfully.\n\r",ch); ch->pcdata->h_vnum = i; do_asave(ch, "area"); save_area(ch->in_room->area); edit_done(ch,""); return; } void do_hname( CHAR_DATA *ch, char *argument ) { int cost = 500; if ( !HAS_HOME( ch ) ) { send_to_char("If you only had a home...\n\r",ch); return; } if ( !IS_HOME( ch ) ) { send_to_char( "You've got to be in your house to do that.\n\r", ch ); return; } if (ch->platinum < cost) { printf_to_char( ch, "It cost %d to change the name of a room in your house.\n\r", cost ); return; } if (argument[0] == '\0') { send_to_char("Change the name to what?\n\r",ch); return; } ch->platinum -= cost; send_to_char("Ok.\n\r",ch); redit_name(ch,argument); save_area(ch->in_room->area); edit_done(ch,""); return; } void do_hdesc( CHAR_DATA *ch, char *argument ) { int cost = 500; if ( !HAS_HOME( ch ) ) { send_to_char("If you only had a home...\n\r",ch); return; } if ( !IS_HOME( ch ) ) { send_to_char("You gotta be in your house.\n\r",ch); return; } if (ch->platinum < cost) { printf_to_char( ch, "It cost %d platinum to change a description.\n\r", cost ); return; } ch->platinum -= cost; send_to_char("Ok.\n\r",ch); ch->desc->pEdit = ch->in_room; ch->desc->editor = 2; ch->pcdata->hchange = TRUE; redit_desc(ch,""); edit_done(ch,""); save_area(ch->in_room->area); return; } void do_home( CHAR_DATA *ch, char *argument ) { char buf[MSL]; CHAR_DATA *victim; ROOM_INDEX_DATA *location; int track; if (IS_NPC(ch) && IS_SET(ch->act,ACT_PET)) { send_to_char("Only players can go home.\n\r",ch); return; } if ( !HAS_HOME( ch ) ) { send_to_char("If you only had a home...\n\r",ch); return; } if(IS_NPC(ch)) location = get_room_index(ch->master->pcdata->h_vnum); else location = get_room_index(ch->pcdata->h_vnum); if (location == NULL) { send_to_char( "Yikes write a note to immortal and let them know your house is Null.\n\r", ch ); return; } act( "$n prays for transportation!", ch, 0, 0, TO_ROOM ); if ( ch->in_room == location ) return; if ( ( IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL) || IS_AFFECTED(ch, AFF_CURSE)) && (ch->level <= HERO) ) { act( "$G has forsaken you.", ch, NULL, NULL, TO_CHAR ); return; } if (ch->pcdata->pkflag > 1) { send_to_char("You cannot recall for 1 tick after Pkill Fights!.\n\r",ch); return; } if ( ( victim = ch->fighting ) != NULL ) { int lose,skill; skill = get_skill(ch,gsn_recall); if ( number_percent() < 80 * skill / 100 ) { check_improve(ch,gsn_recall,FALSE,6); WAIT_STATE( ch, 4 ); sprintf( buf, "You failed!.\n\r"); send_to_char( buf, ch ); return; } lose = (ch->desc != NULL) ? 50 : 100; gain_exp( ch, 0 - lose ); check_improve(ch,gsn_recall,TRUE,4); sprintf( buf, "You flee home from combat! You lose %d exps.\n\r", lose ); send_to_char( buf, ch ); if ( !IS_NPC(ch) ) { if ( !IS_NPC(victim) && ch->attacker == TRUE) { send_to_char( "You flee from combat and go home.\n\r", ch ); send_to_char( "You lose some hit points in the process.\n\r", ch ); ch->hit -= (ch->hit/4); } } stop_fighting( ch, TRUE ); } act( "$n disappears.", ch, NULL, NULL, TO_ROOM ); /* if (IS_NPC(ch) || !IS_IMMORTAL(ch)) { for (track = MAX_TRACK-1; track > 0; track--) { ch->track_to[track] = ch->track_to[track-1]; ch->track_from[track] = ch->track_from[track-1]; } ch->track_from[0] = ch->in_room->vnum; ch->track_to[0] = 0; } */ char_from_room( ch ); char_to_room( ch, location ); act( "$n appears in the room.", ch, NULL, NULL, TO_ROOM ); do_look( ch, "auto" ); if (ch->pet != NULL) do_home(ch->pet,""); return; } void do_invite(CHAR_DATA *ch,char *argument) { CHAR_DATA *victim; char buf[MSL]; if (argument[0] == '\0') { send_to_char("Invite whom to your home?\n\r",ch); return; } if ((victim = get_char_world(ch,argument)) == NULL) { send_to_char("Who is that?\n\r",ch); return; } if ( !IS_HOME( ch ) ) { send_to_char("Can't invite someone to your house when you aren't in it.\n\r",ch); return; } if (ch == victim) { send_to_char("Lonely person, huh?\n\r",ch); return; } printf_to_char( victim,"%s has invited you to come to %s house!\n\r",ch->name, ch->sex == 0 ? "It's" : ch->sex == 1 ? "His" : "Her" ); send_to_char(buf,victim); printf_to_char( ch, "You have invited %s into your house!\n\r", victim->name ); victim->pcdata->hinvite = ch->pcdata->h_vnum; } void do_join(CHAR_DATA *ch,char *argument) { int ohvnum = 0; if (ch->pcdata->hinvite == 0) { send_to_char("You haven't been invited anywhere.\n\r",ch); return; } if (ch->pcdata->pkflag > 1) { send_to_char("You cannot recall for 1 tick after Pkill Fights!.\n\r",ch); return; } ohvnum = ch->pcdata->h_vnum; ch->pcdata->h_vnum = ch->pcdata->hinvite; do_home(ch,""); ch->pcdata->h_vnum = ohvnum; ch->pcdata->hinvite = 0; } void home_sell( CHAR_DATA *ch, int cost ) { char buf[MSL]; int i; send_to_char( "Ok. Attempting to sell your home.\n\r\n\r", ch ); for ( i = ch->pcdata->h_vnum; i < ch->pcdata->h_vnum + 5; i++ ) { sprintf( buf, "%d", i ); redit_delete( ch, buf ); } if ( ch->pcdata->security <= 5 ) ch->pcdata->security = 0; ch->platinum += ( cost / 2 ); ch->pcdata->h_vnum = 0; send_to_char( "\n\rYou have successfully sold your house.\n\r", ch ); printf_to_char( ch, "You recieve %d platinum for selling it.\n\r", cost / 2 ); return; } void do_boot( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; if ( argument[0] == '\0' ) { send_to_char( "Who would you like to boot out of your house?\n\r", ch ); return; } if ((victim = get_char_world(ch,argument)) == NULL) { send_to_char("Who is that?\n\r",ch); return; } if ( !IS_HOME( ch ) ) { send_to_char("You can't boot someone if your not in your house!\n\r", ch ); return; } if ((victim->in_room->vnum < ch->pcdata->h_vnum) || (victim->in_room->vnum > ch->pcdata->h_vnum + 4)) { send_to_char("You can't boot someone if their not in your house!\n\r",ch); return; } printf_to_char( ch, "You get in %s's face and yell at %s to get out of your house!\n\r", victim->name, victim->sex == 0 ? "It" : victim->sex == 1 ? "Him" : "Her" ); printf_to_char( victim, "%s begins yelling at you, and tells you to get out of %s house!\n\r", ch->name, ch->sex == 0 ? "It's" : ch->sex == 1 ? "His" : "Her" ); printf_to_char( victim, "You have been kicked out of %s's house!\n\r", ch->name ); do_recall( victim, "" ); return; }