/**************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvements 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 *
* benefiting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************
* ROM 2.4 is copyright 1993-1998 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@hypercube.org) *
* Gabrielle Taylor (gtaylor@hypercube.org) *
* Brian Moore (zump@rom.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Rom24/doc/rom.license *
***************************************************************************
* 1stMud ROM Derivative (c) 2001-2004 by Markanth *
* http://www.firstmud.com/ <markanth@firstmud.com> *
* By using this code you have agreed to follow the term of *
* the 1stMud license in ../doc/1stMud/LICENSE *
***************************************************************************/
#include "merc.h"
#include "interp.h"
#include "recycle.h"
#include "olc.h"
#include "tables.h"
#include "vnums.h"
Declare_Do_F (home_buy);
Declare_Do_F (home_add);
Declare_Do_F (home_furnish);
Declare_Do_F (home_unfurnish);
Declare_Do_F (home_sell);
Declare_Do_F (home_describe);
Declare_Do_F (home_name);
Declare_Do_F (home_evict);
Declare_Do_F (home_invite);
Declare_Do_F (home_accept);
Declare_Do_F (home_deny);
Declare_Do_F (do_get_key);
Declare_Do_F (home_help);
Declare_Do_F (home_link);
Declare_Do_F (home_unlink);
Declare_Do_F (do_gohome);
Declare_Do_F (home_door);
Declare_Do_F (home_recall);
Proto (void unlink_reset, (RoomIndex *, ResetData *));
#define HOUSE_PRICE 5000000
#define ROOM_PRICE 3005000
struct home_type
{
vnum_t vnum;
money_t cost;
int quest;
int tp;
char *name;
char *list;
int type;
flag_t room_flags;
};
const struct home_type home_table[] = {
{
0, 125000, 10, 0, "healrate", "Up a rooms Heal Rate by 50", ROOM_VNUM,
0},
{0, 125000, 10, 0, "manarate", "Up a rooms Mana Rate by 50", ROOM_VNUM,
0},
{0, 125000, 10, 0, "saferoom", "Make a safe room", ROOM_VNUM, ROOM_SAFE},
{
0, 0, 0, 0, NULL, NULL, 0}
};
bool
is_home_owner (CharData * ch, RoomIndex * pHome)
{
int i;
if (pHome == NULL)
return false;
if (!ch || IsNPC (ch))
return false;
for (i = 0; i < HAS_HOME (ch); i++)
if (ch->pcdata->home[i] == pHome->vnum)
return true;
return false;
}
int
tally_resets (RoomIndex * pRoom, money_t cost, int trivia, int quest)
{
ResetData *pReset;
int rcount = 0, i;
if (pRoom == NULL)
return 0;
for (i = 0; home_table[i].name != NULL; i++)
{
if (home_table[i].type == VNUM_NONE || home_table[i].vnum <= 0)
continue;
for (pReset = pRoom->reset_first; pReset != NULL; pReset = pReset->next)
{
if (pReset->arg1 == home_table[i].vnum)
{
cost += home_table[i].cost / 3;
trivia += home_table[i].tp / 3;
quest += home_table[i].quest / 3;
rcount++;
}
}
}
return rcount;
}
bool
get_key (CharData * ch)
{
ObjIndex *keyindex = NULL;
ObjData *key = NULL;
if (!ch || IsNPC (ch) || ch->pcdata->home_key <= 0)
return false;
if ((keyindex = get_obj_index (ch->pcdata->home_key)) == NULL)
{
chprintln (ch,
"Could not find your key, please have an immortal fix this.");
return false;
}
if (get_obj_here (ch, NULL, keyindex->name) != NULL)
{
chprintln (ch, "You already have a key to your home.");
return true;
}
if ((key = create_object (keyindex, 1)) == NULL)
return false;
obj_to_char (key, ch);
chprintln (ch, "A house key appears in your inventory.");
return true;
}
Do_Fun (do_get_key)
{
get_key (ch);
}
Do_Fun (home_help)
{
if (ch->pcdata->home_invite != 0)
{
cmd_syntax (ch, NULL, n_fun,
"accept - accept an invitation to someone's home",
"deny - turn down an invitation to someone's home",
NULL);
}
if (!HAS_HOME (ch))
cmd_syntax (ch, NULL, n_fun,
"buy - purchase a home in <direction> (must be in the right area)",
NULL);
else
{
cmd_syntax (ch, NULL, n_fun,
"sell - sells your home completly for 1/3 the price",
"add - adds another room in <direction>, must be in your home",
"describe - describes a room using the string editor",
"name - name or rename's a room",
"furnish - add objects or mobiles to a room in your home",
"unfurnish - sells objects or mobiles placed in your home",
"key - gets a replacement key for your home",
"door - sets a door on a room",
"recall - sets your recall room for 'gohome'",
"evict - kick's someone out of your home",
"invite - invite someone to your home",
"link - link a room to a specified area",
"unlink - Unlink an exit", NULL);
}
}
Do_Fun (do_home)
{
if (!ch)
return;
if (IsNPC (ch))
{
chprintln (ch, "Mobiles don't have homes =).");
return;
}
vinterpret (ch, n_fun, argument, "buy", home_buy, "add", home_add,
"sell", home_sell, "describe", home_describe, "name",
home_name, "furnish", home_furnish, "unfurnish",
home_unfurnish, "key", do_get_key, "recall", do_gohome,
"evict", home_evict, "link", home_link, "unlink",
home_unlink, "list", home_help, "invite", home_invite,
"accept", home_accept, "deny", home_deny, NULL, home_help);
}
Do_Fun (home_buy)
{
RoomIndex *pRoom = NULL;
ObjIndex *pObj;
AreaData *pArea;
ExitData *pExit, *toExit;
int door, rev, iHash;
vnum_t i;
if (!ch || IsNPC (ch))
return;
pArea = ch->in_room->area;
if (!pArea || !IsSet (pArea->area_flags, AREA_PLAYER_HOMES))
{
chprintln (ch, "Player Homes are not allowed in this area.");
return;
}
if (!check_worth (ch, HOUSE_PRICE, VALUE_GOLD))
{
chprintlnf (ch, "{wIt costs %d gold to buy a home.", HOUSE_PRICE);
return;
}
if (ch->pcdata->trivia < 40)
{
chprintln (ch, "It costs 40 trivia points to buy a house.");
return;
}
if (HAS_HOME (ch))
{
chprintlnf (ch,
"{wYou already own a home, use '%s add' or '%s furnish'.",
cmd_name (do_home), cmd_name (do_home));
return;
}
if (!IsSet (ch->in_room->room_flags, HOME_ENTRANCE))
{
chprintln (ch, "You must be at an entrance to a future home.");
return;
}
if ((door = get_direction (argument)) == -1 || door > 3)
{
chprintln (ch,
"Which direction from here do you want to start your home?");
return;
}
if (ch->in_room->exit[door])
{
chprintln (ch, "A room already exits in that location.");
return;
}
for (i = pArea->min_vnum; i < pArea->max_vnum; i++)
{
if ((get_obj_index (i)) == NULL)
{
pObj = new_obj_index ();
pObj->vnum = i;
pObj->area = pArea;
replace_strf (&pObj->name, "key %s home", ch->name);
replace_strf (&pObj->short_descr, "%s's key",
capitalize (ch->name));
replace_strf (&pObj->description,
"The key to %s's home is here.",
capitalize (ch->name));
pObj->item_type = ITEM_KEY;
SetBit (pObj->wear_flags, ITEM_TAKE);
SetBit (pObj->wear_flags, ITEM_HOLD);
pObj->condition = -1;
iHash = i % MAX_KEY_HASH;
LinkSingle (pObj, obj_index_hash[iHash], next);
ch->pcdata->home_key = pObj->vnum;
break;
}
}
for (i = pArea->min_vnum; i < pArea->max_vnum; i++)
{
if ((get_room_index (i)) == NULL)
{
pRoom = new_room_index ();
pRoom->area = pArea;
pRoom->vnum = i;
pRoom->sector_type = SECT_INSIDE;
replace_strf (&pRoom->name, "%s\'s Home", capitalize (ch->name));
replace_str (&pRoom->description,
"This is your room description. You can edit this with HOME DESCRIBE."
NEWLINE);
replace_str (&pRoom->owner, ch->name);
SetBit (pRoom->room_flags, ROOM_INDOORS | ROOM_SAVE_OBJS);
iHash = i % MAX_KEY_HASH;
LinkSingle (pRoom, room_index_hash[iHash], next);
pExit = new_exit ();
pExit->u1.to_room = pRoom;
pExit->orig_door = door;
SetBit (pExit->rs_flags,
EX_ISDOOR | EX_CLOSED | EX_NOPASS | EX_PICKPROOF |
EX_DOORBELL);
pExit->exit_info = pExit->rs_flags;
replace_str (&pExit->keyword, "door");
replace_strf (&pExit->description,
"You see the door to %s's home.",
capitalize (ch->name));
ch->in_room->exit[door] = pExit;
rev = rev_dir[door];
toExit = new_exit ();
toExit->u1.to_room = ch->in_room;
toExit->orig_door = rev;
toExit->rs_flags = pExit->rs_flags;
RemBit (toExit->rs_flags, EX_DOORBELL);
toExit->exit_info = toExit->rs_flags;
replace_str (&toExit->keyword, "door");
replace_strf (&toExit->description,
"You see the door to %s's home.",
capitalize (ch->name));
pRoom->exit[rev] = toExit;
if (get_key (ch) == true)
{
SetBit (pExit->rs_flags, EX_LOCKED);
pExit->exit_info = pExit->rs_flags;
pExit->key = ch->pcdata->home_key;
}
SetBit (pArea->area_flags, AREA_CHANGED);
break;
}
}
if (!pRoom)
{
chprintln (ch,
"A new home could not be created for you. please contact an immortal.");
return;
}
ch->pcdata->home[HAS_HOME (ch)] = pRoom->vnum;
HAS_HOME (ch) += 1;
deduct_cost (ch, HOUSE_PRICE, VALUE_GOLD);
ch->pcdata->trivia -= 40;
chprintln (ch, "Congratulations, you are now a proud home owner.");
save_char_obj (ch);
return;
}
Do_Fun (home_add)
{
RoomIndex *pRoom = NULL;
AreaData *pArea;
ExitData *pExit;
int door, rev, iHash;
vnum_t i;
if (!ch || IsNPC (ch))
return;
pArea = ch->in_room->area;
if (!pArea || !IsSet (pArea->area_flags, AREA_PLAYER_HOMES))
{
chprintln (ch, "Player Homes are not allowed in this area.");
return;
}
if (!HAS_HOME (ch))
{
chprintlnf (ch, "Use '%s buy' to purchase a home first.",
cmd_name (do_home));
return;
}
if (!check_worth (ch, ROOM_PRICE, VALUE_GOLD))
{
chprintln (ch, "{wYou don't have enough to buy a another room.");
return;
}
if (ch->pcdata->quest.points < 200)
{
chprintln (ch, "{wYou need 200 questpoints to buy another room.");
return;
}
if (HAS_HOME (ch) == PC_HOME_COUNT)
{
chprintln (ch, "{wYou have the max allowable rooms in your house.");
return;
}
if (!is_home_owner (ch, ch->in_room))
{
chprintln (ch, "You must add only to your home!");
return;
}
if ((door = get_direction (argument)) == -1 || door > 3)
{
chprintln (ch, "Which direction from here do you want the new room?");
return;
}
if (ch->in_room->exit[door])
{
chprintln (ch, "A room already exits in that location.");
return;
}
for (i = pArea->min_vnum; i < pArea->max_vnum; i++)
{
if ((get_room_index (i)) == NULL)
{
pRoom = new_room_index ();
pRoom->area = pArea;
pRoom->vnum = i;
pRoom->sector_type = SECT_INSIDE;
replace_strf (&pRoom->name, "%s\'s %d Room",
capitalize (ch->name), HAS_HOME (ch) + 1);
replace_str (&pRoom->description,
"This is your room description. You can edit this with HOME DESCRIBE."
NEWLINE);
replace_str (&pRoom->owner, ch->name);
SetBit (pRoom->room_flags, ROOM_INDOORS | ROOM_SAVE_OBJS);
iHash = i % MAX_KEY_HASH;
LinkSingle (pRoom, room_index_hash[iHash], next);
ch->in_room->exit[door] = new_exit ();
ch->in_room->exit[door]->u1.to_room = pRoom;
ch->in_room->exit[door]->orig_door = door;
rev = rev_dir[door];
pExit = new_exit ();
pExit->u1.to_room = ch->in_room;
pExit->orig_door = rev;
pRoom->exit[rev] = pExit;
break;
}
}
if (!pRoom)
{
chprintln (ch,
"A new room could not be created for you. please contact an immortal.");
return;
}
ch->pcdata->home[HAS_HOME (ch)] = pRoom->vnum;
HAS_HOME (ch) += 1;
deduct_cost (ch, ROOM_PRICE, VALUE_GOLD);
ch->pcdata->quest.points -= 200;
chprintln
(ch, "The mayors hired contractors come and do additions to your home.");
chprintlnf (ch, "Your home now contains %d rooms.", HAS_HOME (ch));
save_char_obj (ch);
SetBit (pArea->area_flags, AREA_CHANGED);
return;
}
Do_Fun (home_sell)
{
RoomIndex *pRoom = NULL;
int home, i = 0, rooms = 0;
money_t cost = 0;
int quest = 0;
int tp = 0;
char buf[MSL];
if (!ch || IsNPC (ch))
return;
if (!(rooms = HAS_HOME (ch)))
{
chprintln (ch, "You don't have a home yet.");
return;
}
if (NullStr (argument))
{
chprintln (ch,
"This command allows you to sell your home. The Mayors");
chprintln (ch,
"contractors will completly demolish your home when it is sold,");
chprintln (ch,
"and you will be compensated half the cost of the home,");
chprintln (ch, "including any items you have purchased.");
chprintln (ch,
"{ROnce your home is sold, it cannot be brought back!!!{x");
cmd_syntax (ch, NULL, n_fun, "confirm", NULL);
return;
}
else if (!str_cmp (argument, "confirm"))
{
bool found = false;
sprintf (buf, "%ld", HOME_KEY (ch));
oedit_delete (NULL, NULL, buf);
for (home = 0; home < PC_HOME_COUNT; home++)
{
if (!found && ch->pcdata->home[home] == HOME_ROOM (ch))
found = true;
if ((pRoom = get_room_index (ch->pcdata->home[home])) != NULL)
{
SetBit (pRoom->area->area_flags, AREA_CHANGED);
i += tally_resets (pRoom, cost, tp, quest);
sprintf (buf, "%ld", ch->pcdata->home[home]);
if (redit_delete (NULL, NULL, buf))
cost += ROOM_PRICE / 3;
}
}
if (!found && HOME_ROOM (ch)
&& (pRoom = get_room_index (HOME_ROOM (ch))) != NULL)
{
SetBit (pRoom->area->area_flags, AREA_CHANGED);
i += tally_resets (pRoom, cost, tp, quest);
sprintf (buf, "%ld", HOME_ROOM (ch));
if (redit_delete (NULL, NULL, buf))
cost += ROOM_PRICE / 3;
}
add_cost (ch, cost, VALUE_GOLD);
ch->pcdata->trivia += tp;
ch->pcdata->quest.points += quest;
chprintlnf
(ch,
"Your home {R(%d rooms) {G(%d furnishings){x has been sold and you are now {Y%ld{x gold coins richer!",
rooms, i, cost);
memset (ch->pcdata->home, 0, MAX_HOME_VNUMS);
save_char_obj (ch);
return;
}
else
{
home_sell (n_fun, ch, "");
return;
}
}
Do_Fun (home_door)
{
int door;
char arg1[MIL], arg2[MIL];
ExitData *pexit;
if (!ch || IsNPC (ch))
return;
if (!HAS_HOME (ch))
{
chprintln (ch, "You have to BUY a home before you can describe it.");
return;
}
if (!is_home_owner (ch, ch->in_room))
{
chprintln (ch, "But you do not own this room!");
return;
}
argument = first_arg (argument, arg1, false);
argument = first_arg (argument, arg2, false);
if (NullStr (arg1))
{
cmd_syntax (ch, NULL, n_fun,
"<exit> <flag> - flag an exit.",
"<exit> list - list exit flags.",
"<exit> key <object> - make a key for exit.",
"<exit> name <string> - name an exit.",
"<exit> desc <string> - describe an exit.", NULL);
return;
}
if ((door = get_direction (arg1)) != -1
&& (pexit = ch->in_room->exit[door]) != NULL)
{
flag_t flag;
if (!str_prefix (arg2, "list"))
{
show_flags (ch, exit_flags);
return;
}
else if ((flag = flag_value (exit_flags, arg2)) != NO_FLAG)
{
ExitData *toExit;
ToggleBit (pexit->rs_flags, flag);
if ((IsSet (pexit->rs_flags, EX_PICKPROOF)
|| IsSet (pexit->rs_flags, EX_EASY)
|| IsSet (pexit->rs_flags, EX_HARD)
|| IsSet (pexit->rs_flags, EX_INFURIATING))
&& !IsSet (pexit->rs_flags, EX_LOCKED))
{
ToggleBit (pexit->rs_flags, EX_LOCKED);
}
if ((IsSet (pexit->rs_flags, EX_LOCKED)
|| IsSet (pexit->rs_flags, EX_NOPASS))
&& !IsSet (pexit->rs_flags, EX_CLOSED))
{
ToggleBit (pexit->rs_flags, EX_CLOSED);
}
if (IsSet (pexit->rs_flags, EX_CLOSED)
&& !IsSet (pexit->rs_flags, EX_ISDOOR))
{
ToggleBit (pexit->rs_flags, EX_ISDOOR);
}
pexit->exit_info = pexit->rs_flags;
if (pexit->u1.to_room
&& (toExit = pexit->u1.to_room->exit[rev_dir[door]]))
{
toExit->rs_flags = pexit->rs_flags;
if ((IsSet (toExit->rs_flags, EX_PICKPROOF)
|| IsSet (toExit->rs_flags, EX_EASY)
|| IsSet (toExit->rs_flags, EX_HARD)
|| IsSet (toExit->rs_flags, EX_INFURIATING))
&& !IsSet (toExit->rs_flags, EX_LOCKED))
{
ToggleBit (toExit->rs_flags, EX_LOCKED);
}
if ((IsSet (toExit->rs_flags, EX_LOCKED)
|| IsSet (toExit->rs_flags, EX_NOPASS))
&& !IsSet (toExit->rs_flags, EX_CLOSED))
{
ToggleBit (toExit->rs_flags, EX_CLOSED);
}
if (IsSet (toExit->rs_flags, EX_CLOSED)
&& !IsSet (toExit->rs_flags, EX_ISDOOR))
{
ToggleBit (toExit->rs_flags, EX_ISDOOR);
}
toExit->exit_info = toExit->rs_flags;
}
act ("Exit is now $t.", ch, arg2, pexit, TO_CHAR);
SetBit (ch->in_room->area->area_flags, AREA_CHANGED);
return;
}
else if (!str_prefix (arg2, "key"))
{
ObjData *key;
if ((key = get_obj_here (ch, NULL, argument)) == NULL
|| key->item_type != ITEM_KEY)
{
chprintln (ch, "No such key!");
return;
}
pexit->key = key->pIndexData->vnum;
SetBit (ch->in_room->area->area_flags, AREA_CHANGED);
act ("Exit now uses $p as a key.", ch, key, pexit->keyword,
TO_CHAR);
return;
}
else if (!str_prefix (arg2, "name"))
{
replace_str (&pexit->keyword, argument);
if (NullStr (argument))
chprintln (ch, "Exit name removed.");
else
act ("Exit is now named $T.", ch, dir_name[door], argument,
TO_CHAR);
SetBit (ch->in_room->area->area_flags, AREA_CHANGED);
return;
}
else if (!str_prefix (arg2, "describe"))
{
replace_str (&pexit->description, argument);
if (NullStr (argument))
chprintln (ch, "Exit description removed.");
else
act ("Exit is now described as $T.", ch, dir_name[door],
argument, TO_CHAR);
SetBit (ch->in_room->area->area_flags, AREA_CHANGED);
return;
}
}
home_door (n_fun, ch, "");
}
Do_Fun (home_describe)
{
RoomIndex *loc;
char buf[MSL];
int len;
bool found = false;
loc = ch->in_room;
if (!ch || IsNPC (ch))
return;
if (!HAS_HOME (ch))
{
chprintln (ch, "You have to BUY a home before you can describe it.");
return;
}
if (!is_home_owner (ch, loc))
{
chprintln (ch, "But you do not own this room!");
return;
}
if (NullStr (argument))
{
chprintln (ch, "This command allows you to describe your home.");
chprintln (ch, "You should not describe items that are in the room,");
chprintln (ch,
"rather allowing the furnishing of the home to do that.");
chprintln (ch,
"If you currently own this room, you will be placed into.");
chprintln (ch,
"the room editor. Be warned that while in the room editor,");
chprintln (ch,
"you are only allowed to type the description. If you are");
chprintln (ch,
"unsure or hesitant about this, please note the Immortals,");
chprintln (ch, "or better, discuss the how-to's with a Builder.");
chprintlnf (ch,
"If Using the string editor bothers you type /q on a new line"
NEWLINE "and use the syntax: %s +/- <string>{x", n_fun);
string_append (ch, &loc->description);
SetBit (loc->area->area_flags, AREA_CHANGED);
return;
}
else
{
buf[0] = '\0';
if (argument[0] == '-')
{
if (NullStr (loc->description))
{
chprintln (ch, "No lines left to remove.");
return;
}
strcpy (buf, loc->description);
for (len = strlen (buf); len > 0; len--)
{
if (buf[len] == '\r')
{
if (!found)
{
if (len > 0)
len--;
found = true;
}
else
{
buf[len + 1] = '\0';
replace_str (&loc->description, buf);
chprintln (ch, "OK.");
return;
}
}
}
buf[0] = '\0';
replace_str (&loc->description, buf);
chprintln (ch, "Description cleared.");
return;
}
if (argument[0] == '+')
{
if (loc->description != NULL)
strcat (buf, loc->description);
argument++;
while (isspace (*argument))
argument++;
}
if (strlen (buf) + strlen (argument) >= MSL - 2)
{
chprintln (ch, "Description too long.");
return;
}
strcat (buf, argument);
strcat (buf, NEWLINE);
replace_str (&loc->description, buf);
SetBit (loc->area->area_flags, AREA_CHANGED);
}
return;
}
Do_Fun (home_name)
{
RoomIndex *loc;
loc = ch->in_room;
if (!ch || IsNPC (ch))
return;
if (!HAS_HOME (ch))
{
chprintln (ch, "You have to BUY a home before you can rename it.");
return;
}
if (!is_home_owner (ch, loc))
{
chprintln (ch, "But you do not own this room!");
return;
}
if (NullStr (argument))
{
chprintln (ch, "Change the this room title to what?");
return;
}
if (cstrlen (argument) > 25)
{
chprintln (ch, "This is the name, not the description.");
return;
}
replace_str (&loc->name, argument);
SetBit (loc->area->area_flags, AREA_CHANGED);
return;
}
Lookup_Fun (furnish_lookup)
{
int i;
for (i = 0; home_table[i].name != NULL; i++)
{
if (is_name (name, home_table[i].name))
return i;
}
return -1;
}
Do_Fun (home_furnish)
{
ResetData *loc_reset, *pReset;
ObjData *furn = NULL;
ObjIndex *pObj = NULL;
CharData *moby = NULL;
CharIndex *pMob = NULL;
int i;
if (!ch || IsNPC (ch))
return;
if (!HAS_HOME (ch))
{
chprintln (ch, "You have to BUY a home before you can furnish it.");
return;
}
if (!is_home_owner (ch, ch->in_room))
{
chprintln (ch, "But you do not own this room!");
return;
}
if (NullStr (argument) || !str_cmp (argument, "list"))
{
chprintln (ch, "This command allows you to furnish your home.");
chprintln (ch,
"You must be standing in your home. You cannot have more");
chprintln (ch, "than five items and five mobiles in your home.");
chprintln (ch,
"Other things like heal/mana rate have a limit instead.");
cmd_syntax (ch, NULL, n_fun, "<option>", NULL);
for (i = 0; home_table[i].name != NULL; i++)
{
switch (home_table[i].type)
{
default:
case VNUM_NONE:
case ROOM_VNUM:
break;
case MOB_VNUM:
pMob = get_char_index (home_table[i].vnum);
break;
case OBJ_VNUM:
pObj = get_obj_index (home_table[i].vnum);
break;
}
chprintlnf (ch, "\t%-15s - %ld gold, %dqp, %dtp (%s)",
pMob ? pMob->short_descr : pObj ? pObj->
short_descr : home_table[i].list, home_table[i].cost,
home_table[i].quest, home_table[i].tp,
home_table[i].name);
pMob = NULL;
pObj = NULL;
}
return;
}
else
{
if ((i = furnish_lookup (argument)) == -1)
{
chprintln (ch, "Furnish what?");
}
if (!check_worth (ch, home_table[i].cost, VALUE_GOLD))
{
chprintlnf
(ch, "You don't have enough gold for to buy a %s.",
home_table[i].name);
return;
}
if (ch->pcdata->quest.points < home_table[i].quest)
{
chprintlnf (ch, "You need %s to buy a %s.",
intstr (home_table[i].quest, "questpoint"),
home_table[i].name);
return;
}
if (ch->pcdata->trivia < home_table[i].tp)
{
chprintlnf (ch, "You need %s to buy a %s.",
intstr (home_table[i].quest, "trivia point"),
home_table[i].name);
return;
}
if (home_table[i].type == VNUM_NONE)
{
if (!str_cmp (home_table[i].name, "healrate"))
{
if (ch->in_room->heal_rate >= 200)
{
chprintln (ch, "This rooms heal rate can't go any higher.");
return;
}
ch->in_room->heal_rate = Min (ch->in_room->heal_rate + 50, 200);
}
if (!str_cmp (home_table[i].name, "manarate"))
{
if (ch->in_room->mana_rate >= 200)
{
chprintln (ch, "This rooms mana rate can't go any higher.");
return;
}
ch->in_room->mana_rate = Min (ch->in_room->mana_rate + 50, 200);
}
}
else if (home_table[i].type == OBJ_VNUM)
{
for (furn = ch->in_room->content_first; furn;
furn = furn->next_content)
{
if (furn->pIndexData->vnum == home_table[i].vnum)
{
chprintln
(ch, "You already have one of those in this room.");
return;
}
}
if ((pObj = get_obj_index (home_table[i].vnum)) != NULL)
{
furn = create_object (pObj, pObj->level);
obj_to_room (furn, ch->in_room);
}
else
chprintln
(ch, "Cannot find that object, please contact an immortal.");
}
else if (home_table[i].type == MOB_VNUM)
{
for (pReset = ch->in_room->reset_first; pReset != NULL;
pReset = pReset->next)
{
if (pReset->command == 'M'
&& pReset->arg1 == home_table[i].vnum)
{
chprintln
(ch, "You already have one of those in this room.");
return;
}
}
if ((pMob = get_char_index (home_table[i].vnum)) != NULL)
{
moby = create_mobile (pMob);
loc_reset = new_reset ();
loc_reset->command = 'M';
loc_reset->arg1 = pMob->vnum;
loc_reset->arg2 =
ch->in_room->area->max_vnum - ch->in_room->area->min_vnum;
loc_reset->arg3 = ch->in_room->vnum;
loc_reset->arg4 = 1;
add_reset (ch->in_room, loc_reset, 0);
char_to_room (moby, ch->in_room);
}
else
chprintln
(ch, "Cannot find that mobile, please contact an immortal.");
}
else
{
chprintln
(ch,
"Unable to complete your request. Please inform an Immortal.");
return;
}
if (home_table[i].room_flags > 0)
SetBit (ch->in_room->room_flags, home_table[i].room_flags);
deduct_cost (ch, home_table[i].cost, VALUE_GOLD);
ch->pcdata->quest.points -= home_table[i].quest;
ch->pcdata->trivia -= home_table[i].tp;
chprintlnf
(ch,
"You have been deducted %ld gold, %dqp and %dtp for your purchase.",
home_table[i].cost, home_table[i].quest, home_table[i].tp);
SetBit (ch->in_room->area->area_flags, AREA_CHANGED);
return;
}
}
Do_Fun (home_unfurnish)
{
ResetData *pReset = NULL, *pResNext;
ObjData *obj, *obj_next;
CharData *mob, *mob_next;
int i = 0;
bool found = false;
if (!ch || IsNPC (ch))
return;
if (!HAS_HOME (ch))
{
chprintln (ch, "You have to BUY a home before you can furnish it.");
return;
}
if (!ch->in_room || !is_home_owner (ch, ch->in_room))
{
chprintln (ch, "But you do not own this room!");
return;
}
if (NullStr (argument))
{
chprintln (ch, "Unfurnish which object?.");
return;
}
else
{
for (i = 0; home_table[i].name != NULL; i++)
{
if (home_table[i].type == VNUM_NONE || home_table[i].vnum <= 0)
continue;
if (home_table[i].type == MOB_VNUM)
{
for (pReset = ch->in_room->reset_first; pReset;
pReset = pResNext)
{
pResNext = pReset->next;
if (pReset->command == 'M'
&& pReset->arg1 == home_table[i].vnum)
{
unlink_reset (ch->in_room, pReset);
free_reset (pReset);
if (home_table[i].room_flags > 0)
RemBit (ch->in_room->room_flags,
home_table[i].room_flags);
SetBit (ch->in_room->area->area_flags, AREA_CHANGED);
found = true;
for (mob = ch->in_room->person_first; mob != NULL;
mob = mob_next)
{
mob_next = mob->next_in_room;
if (IsNPC (mob)
&& mob->pIndexData->vnum == home_table[i].vnum)
extract_char (mob, true);
}
}
}
}
else if (home_table[i].type == OBJ_VNUM)
{
for (obj = ch->in_room->content_first; obj != NULL;
obj = obj_next)
{
obj_next = obj->next_content;
if (obj->pIndexData->vnum == home_table[i].vnum)
{
extract_obj (obj);
found = true;
if (home_table[i].room_flags > 0)
RemBit (ch->in_room->room_flags,
home_table[i].room_flags);
}
}
}
add_cost (ch, home_table[i].cost / 3, VALUE_GOLD);
ch->pcdata->quest.points += home_table[i].quest / 3;
ch->pcdata->trivia += home_table[i].tp / 3;
chprintlnf
(ch,
"You sell %s back to the mayor for %ld gold, %dqp and %dtp.",
home_table[i].list, home_table[i].cost / 3,
home_table[i].quest / 3, home_table[i].tp / 3);
}
if (!found)
chprintln (ch, "Unable to find your request.");
return;
}
}
Do_Fun (do_gohome)
{
RoomIndex *location = NULL;
int i;
if (!ch)
return;
if (IsNPC (ch))
{
chprintln (ch, "Only players can go home.");
return;
}
if (!HOME_ROOM (ch) || (location = get_room_index (HOME_ROOM (ch))) == NULL)
{
for (i = 0; i < HAS_HOME (ch); i++)
if ((location = get_room_index (ch->pcdata->home[i])) != NULL)
break;
if (location == NULL)
{
chprintln (ch, "You don't have a home *pout*.");
return;
}
}
perform_recall (ch, location, "go home");
return;
}
Do_Fun (home_evict)
{
CharData *victim;
if (!HAS_HOME (ch))
{
chprintln (ch, "You don't have a home to kick them out of.");
return;
}
if (NullStr (argument))
{
cmd_syntax (ch, NULL, n_fun, "evict <char>", NULL);
return;
}
if ((victim = get_char_world (ch, argument)) == NULL)
{
chprintln (ch, "They aren't here.");
return;
}
if (IsNPC (victim))
{
chprintln (ch, "No such player.");
return;
}
if (victim == ch)
{
chprintln (ch, "What would be the point of that?");
return;
}
if (ch->fighting != NULL)
{
chprintln (ch, "Your a little busy right now.");
return;
}
if (!is_home_owner (ch, victim->in_room))
{
chprintln (ch, "They aren't in your home.");
return;
}
if (victim->fighting != NULL)
stop_fighting (victim, true);
char_from_room (victim);
char_to_room (victim, get_room_index (ROOM_VNUM_TEMPLE));
act ("$n has someone escort you out of $s home.", ch, NULL, victim,
TO_VICT);
do_function (victim, &do_look, "auto");
act ("You are no longer welcome in $n's home.", ch, NULL, victim, TO_VICT);
act ("$N is no longer welcome in your home.", ch, NULL, victim, TO_CHAR);
return;
}
Do_Fun (home_link)
{
int door;
AreaData *pArea;
RoomIndex *pRoom, *toRoom = NULL;
char arg[MIL];
vnum_t vnum;
if (!HAS_HOME (ch))
{
chprintlnf (ch, "Use '%s buy' to purchase a home first.",
cmd_name (do_home));
return;
}
if (!check_worth (ch, ROOM_PRICE, VALUE_GOLD))
{
chprintln (ch, "{wYou don't have enough to buy a another room.");
return;
}
if (ch->pcdata->quest.points < 125)
{
chprintln (ch, "It costs 125 quest points to add a link to this room.");
return;
}
if (!is_home_owner (ch, ch->in_room))
{
chprintln (ch, "You must add only to your home!");
return;
}
argument = one_argument (argument, arg);
if ((door = get_direction (arg)) == -1)
{
chprintln (ch, "Which direction from here do you want the new exit?");
return;
}
pRoom = ch->in_room;
if (pRoom->exit[door])
{
chprintln (ch, "An exit already exits in that location.");
return;
}
if (NullStr (argument))
{
chprintln (ch, "Invalid area to link to.");
return;
}
for (pArea = area_first; pArea != NULL; pArea = pArea->next)
{
if (!str_prefix (argument, pArea->name))
break;
}
if (pArea == NULL)
{
chprintln (ch, "Invalid area to link to.");
return;
}
for (vnum = pArea->min_vnum; vnum < pArea->max_vnum; vnum++)
{
if ((toRoom = get_room_index (vnum)) != NULL)
break;
}
if (toRoom == NULL)
{
chprintln (ch, "Unable to link to that area.");
return;
}
pRoom->exit[door] = new_exit ();
pRoom->exit[door]->u1.to_room = toRoom;
pRoom->exit[door]->orig_door = door;
SetBit (pRoom->area->area_flags, AREA_CHANGED);
deduct_cost (ch, ROOM_PRICE, VALUE_GOLD);
ch->pcdata->quest.points -= 125;
chprintlnf (ch, "Exit to %s added.", pArea->name);
}
Do_Fun (home_unlink)
{
char arg[MIL];
RoomIndex *pRoom, *pToRoom;
int rev, door;
if (!HAS_HOME (ch))
{
chprintln (ch, "You don't own a home.");
return;
}
if (!is_home_owner (ch, ch->in_room))
{
chprintln (ch, "You don't own this room!");
return;
}
argument = one_argument (argument, arg);
if ((door = get_direction (arg)) == -1)
{
chprintln (ch,
"Which direction from here do you want to delete the exit?");
return;
}
pRoom = ch->in_room;
if (!pRoom->exit[door])
{
chprintln (ch, "There is no exit in that direction.");
return;
}
rev = rev_dir[door];
pToRoom = pRoom->exit[door]->u1.to_room;
if (pToRoom->area == pRoom->area)
{
chprintln (ch, "You can't unlink that exit.");
return;
}
free_exit (pRoom->exit[door]);
pRoom->exit[door] = NULL;
add_cost (ch, ROOM_PRICE / 3, VALUE_GOLD);
ch->pcdata->quest.points += 125 / 3;
SetBit (pRoom->area->area_flags, AREA_CHANGED);
chprintln (ch, "Exit unlinked.");
return;
}
Do_Fun (home_invite)
{
CharData *vch;
if (NullStr (argument))
{
cmd_syntax (ch, NULL, n_fun, "invite <person>", NULL);
return;
}
if ((vch = get_char_world (ch, argument)) == NULL)
{
chprintln (ch, "They aren't online.");
return;
}
if (IsNPC (vch))
{
chprintln (ch, "You can't invite them.");
return;
}
if (vch == ch)
{
chprintln (ch, "You can't invite yourself.");
return;
}
if (vch->pcdata->home_invite != 0)
{
chprintln (ch, "They have already been invited somewhere.");
return;
}
if (vch->fighting != NULL)
{
chprintln (ch, "They're a little busy right now.");
return;
}
vch->pcdata->home_invite = ch->id;
act
("$n has invited you to $s home. Type '$t accept' to accept the invitation"
NEWLINE
"and be transfered to $s home, or type '$t deny' to cancel the invitation.",
ch, cmd_name (do_home), vch, TO_VICT);
act ("Invitation sent to $N.", ch, NULL, vch, TO_CHAR);
}
Do_Fun (home_accept)
{
CharData *owner;
RoomIndex *pRoom;
int i;
if (ch->pcdata->home_invite == 0)
{
chprintln (ch, "You haven't been invited anywhere.");
return;
}
if (ch->fighting != NULL || InWar (ch))
{
chprintln (ch, "You're a little busy right now.");
return;
}
if ((owner = get_char_vnum (ch->pcdata->home_invite)) == NULL)
{
chprintln (ch,
"Hmm, seems the person who invited you isn't around anymore.");
return;
}
pRoom = NULL;
if ((pRoom = get_room_index (HOME_ROOM (owner))) == NULL)
{
for (i = 0; i < HAS_HOME (ch); i++)
if ((pRoom = get_room_index (owner->pcdata->home[i])) != NULL)
break;
}
if (!pRoom)
{
chprintln (ch, "BUG: inviter doesn't own a home!");
return;
}
char_from_room (ch);
char_to_room (ch, pRoom);
act ("$n arrives.", ch, NULL, NULL, TO_ROOM);
do_function (ch, &do_look, "auto");
ch->pcdata->home_invite = 0;
return;
}
Do_Fun (home_deny)
{
CharData *owner;
if (ch->pcdata->home_invite == 0)
{
chprintln (ch, "You haven't been invited anywhere.");
return;
}
owner = get_char_vnum (ch->pcdata->home_invite);
if (owner)
{
act ("You turn down $N's invitation.", ch, NULL, owner, TO_CHAR);
act ("$n turns down your invitation.", ch, NULL, owner, TO_VICT);
}
else
chprintln (ch, "You turn down the invitation.");
ch->pcdata->home_invite = 0;
}
Do_Fun (home_recall)
{
if (!HAS_HOME (ch))
{
chprintln (ch, "You don't own a home.");
return;
}
if (!is_home_owner (ch, ch->in_room))
{
chprintln (ch, "This isn't your home!");
return;
}
ch->pcdata->home_room = ch->in_room->vnum;
chprintlnf (ch, "You can use '%s' to come back here.",
cmd_name (do_gohome));
}
void
delete_home (CharData * ch)
{
int i;
char buf[MSL];
if (HAS_HOME (ch))
{
RoomIndex *pRoom;
AreaData *pArea = NULL;
for (i = 0; i < PC_HOME_COUNT; i++)
{
if ((pRoom = get_room_index (ch->pcdata->home[i])) != NULL)
{
pArea = pRoom->area;
sprintf (buf, "%ld", ch->pcdata->home[i]);
redit_delete (NULL, NULL, buf);
}
}
sprintf (buf, "%ld", HOME_KEY (ch));
oedit_delete (NULL, NULL, buf);
if (pArea)
SetBit (pArea->area_flags, AREA_CHANGED);
}
}
void
write_room_objs (RoomIndex * pRoom, FileData * fp)
{
if (!pRoom || !pRoom->content_last || !fp)
return;
write_obj (NULL, pRoom->content_last, fp, 0, 0, SAVE_ROOM);
}
void
save_room_objs (void)
{
FileData *fp;
RoomIndex *pRoom;
int iHash;
if ((fp = f_open (ROOM_OBJS_FILE, "w")) != NULL)
{
for (iHash = 0; iHash < MAX_KEY_HASH; iHash++)
{
for (pRoom = room_index_hash[iHash]; pRoom; pRoom = pRoom->next)
{
if (!IsSet (pRoom->room_flags, ROOM_SAVE_OBJS)
&& (!IsSet (pRoom->area->area_flags, AREA_PLAYER_HOMES)
|| NullStr (pRoom->owner)))
continue;
write_room_objs (pRoom, fp);
}
}
f_printf (fp, "#" END_MARK LF);
f_close (fp);
}
}
void
load_room_objs (void)
{
FileData *fp;
log_string ("Loading saved objects...");
if ((fp = f_open (ROOM_OBJS_FILE, "r")) == NULL)
{
bug (ROOM_OBJS_FILE " not found");
}
else
{
for (;;)
{
char letter;
char *word;
letter = read_letter (fp);
if (letter == '*')
{
read_to_eol (fp);
continue;
}
if (letter != '#')
{
bug ("# not found.");
break;
}
word = read_word (fp);
if (!str_cmp (word, get_obj_save_header (SAVE_ROOM)))
read_obj (NULL, fp, SAVE_ROOM);
else if (!str_cmp (word, "END"))
break;
else
{
bug ("bad section.");
break;
}
}
f_close (fp);
}
return;
}