/* ************************************************************************ * File: act.movement.c Part of CircleMUD * * Usage: movement commands, door handling, & sleep/rest/etc state * * * * All rights reserved. See license.doc for complete information. * * * * Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University * * CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. * ************************************************************************ */ #include <stdio.h> #include <string.h> #include "structs.h" #include "utils.h" #include "comm.h" #include "interpreter.h" #include "handler.h" #include "db.h" #include "spells.h" #include "house.h" /* external vars */ extern struct room_data *world; extern struct char_data *character_list; extern struct descriptor_data *descriptor_list; extern struct index_data *obj_index; extern int rev_dir[]; extern char *dirs[]; extern int movement_loss[]; /* external functs */ int special(struct char_data * ch, int cmd, char *arg); void death_cry(struct char_data * ch); /* do_simple_move assumes * 1. That there is no master and no followers. * 2. That the direction exists. * * Returns : * 1 : If succes. * 0 : If fail */ int do_simple_move(struct char_data * ch, int dir, int need_specials_check) { int was_in, need_movement, has_boat = 0; struct obj_data *obj; int special(struct char_data * ch, int cmd, char *arg); /* * Check for special routines (North is 1 in command list, but 0 here) Note * -- only check if following; this avoids 'double spec-proc' bug */ if (need_specials_check && special(ch, dir + 1, "")) return 0; /* charmed? */ if (IS_AFFECTED(ch, AFF_CHARM) && ch->master && ch->in_room == ch->master->in_room) { send_to_char("The thought of leaving your master makes you weep.\r\n", ch); act("$n bursts into tears.", FALSE, ch, 0, 0, TO_ROOM); return 0; } /* if this room or the one we're going to needs a boat, check for one */ if ((world[ch->in_room].sector_type == SECT_WATER_NOSWIM) || (world[EXIT(ch, dir)->to_room].sector_type == SECT_WATER_NOSWIM)) { for (obj = ch->carrying; obj; obj = obj->next_content) if (GET_OBJ_TYPE(obj) == ITEM_BOAT) has_boat = TRUE; if (!has_boat) { send_to_char("You need a boat to go there.\r\n", ch); return 0; } } need_movement = (movement_loss[world[ch->in_room].sector_type] + movement_loss[world[world[ch->in_room].dir_option[dir]->to_room].sector_type]) >> 1; if (GET_MOVE(ch) < need_movement && !IS_NPC(ch)) { if (need_specials_check && ch->master) send_to_char("You are too exhausted to follow.\r\n", ch); else send_to_char("You are too exhausted.\r\n", ch); return 0; } if (IS_SET(ROOM_FLAGS(ch->in_room), ROOM_ATRIUM)) if (!House_can_enter(ch, world[EXIT(ch, dir)->to_room].number)) { send_to_char("That's private property -- no trespassing!\r\n", ch); return 0; } if (GET_LEVEL(ch) < LVL_IMMORT && !IS_NPC(ch)) GET_MOVE(ch) -= need_movement; if (!IS_AFFECTED(ch, AFF_SNEAK)) { sprintf(buf2, "$n leaves %s.", dirs[dir]); act(buf2, TRUE, ch, 0, 0, TO_ROOM); } was_in = ch->in_room; char_from_room(ch); char_to_room(ch, world[was_in].dir_option[dir]->to_room); if (!IS_AFFECTED(ch, AFF_SNEAK)) act("$n has arrived.", TRUE, ch, 0, 0, TO_ROOM); look_at_room(ch, 0); if (IS_SET(ROOM_FLAGS(ch->in_room), ROOM_DEATH) && GET_LEVEL(ch) < LVL_IMMORT) { log_death_trap(ch); death_cry(ch); extract_char(ch); return 0; } return 1; } int perform_move(struct char_data * ch, int dir, int need_specials_check) { int was_in; struct follow_type *k, *next; if (ch == NULL || dir < 0 || dir >= NUM_OF_DIRS) return 0; else if (!EXIT(ch, dir) || EXIT(ch, dir)->to_room == NOWHERE) send_to_char("Alas, you cannot go that way...\r\n", ch); else if (IS_SET(EXIT(ch, dir)->exit_info, EX_CLOSED)) { if (EXIT(ch, dir)->keyword) { sprintf(buf2, "The %s seems to be closed.\r\n", fname(EXIT(ch, dir)->keyword)); send_to_char(buf2, ch); } else send_to_char("It seems to be closed.\r\n", ch); } else { if (!ch->followers) return (do_simple_move(ch, dir, need_specials_check)); was_in = ch->in_room; if (!do_simple_move(ch, dir, need_specials_check)) return 0; for (k = ch->followers; k; k = next) { next = k->next; if ((was_in == k->follower->in_room) && (GET_POS(k->follower) >= POS_STANDING)) { act("You follow $N.\r\n", FALSE, k->follower, 0, ch, TO_CHAR); perform_move(k->follower, dir, 1); } } return 1; } return 0; } ACMD(do_move) { /* * This is basically a mapping of cmd numbers to perform_move indices. * It cannot be done in perform_move because perform_move is called * by other functions which do not require the remapping. */ perform_move(ch, cmd - 1, 0); } int find_door(struct char_data * ch, char *type, char *dir) { int door; if (*dir) { /* a direction was specified */ if ((door = search_block(dir, dirs, FALSE)) == -1) { /* Partial Match */ send_to_char("That's not a direction.\r\n", ch); return -1; } if (EXIT(ch, door)) if (EXIT(ch, door)->keyword) if (isname(type, EXIT(ch, door)->keyword)) return door; else { sprintf(buf2, "I see no %s there.\r\n", type); send_to_char(buf2, ch); return -1; } else return door; else { send_to_char("I really don't see how you can close anything there.\r\n", ch); return -1; } } else { /* try to locate the keyword */ for (door = 0; door < NUM_OF_DIRS; door++) if (EXIT(ch, door)) if (EXIT(ch, door)->keyword) if (isname(type, EXIT(ch, door)->keyword)) return door; sprintf(buf2, "There doesn't seem to be %s %s here.\r\n", AN(type), type); send_to_char(buf2, ch); return -1; } } ACMD(do_open) { int door, other_room; char type[MAX_INPUT_LENGTH], dir[MAX_INPUT_LENGTH]; struct room_direction_data *back; struct obj_data *obj; struct char_data *victim; two_arguments(argument, type, dir); if (!*type) send_to_char("Open what?\r\n", ch); else if (generic_find(argument, FIND_OBJ_INV | FIND_OBJ_ROOM, ch, &victim, &obj)) /* this is an object */ if (GET_OBJ_TYPE(obj) != ITEM_CONTAINER) send_to_char("That's not a container.\r\n", ch); else if (!IS_SET(GET_OBJ_VAL(obj, 1), CONT_CLOSED)) send_to_char("But it's already open!\r\n", ch); else if (!IS_SET(GET_OBJ_VAL(obj, 1), CONT_CLOSEABLE)) send_to_char("You can't do that.\r\n", ch); else if (IS_SET(GET_OBJ_VAL(obj, 1), CONT_LOCKED)) send_to_char("It seems to be locked.\r\n", ch); else { REMOVE_BIT(GET_OBJ_VAL(obj, 1), CONT_CLOSED); send_to_char(OK, ch); act("$n opens $p.", FALSE, ch, obj, 0, TO_ROOM); } else if ((door = find_door(ch, type, dir)) >= 0) /* perhaps it is a door */ if (!IS_SET(EXIT(ch, door)->exit_info, EX_ISDOOR)) send_to_char("That's impossible, I'm afraid.\r\n", ch); else if (!IS_SET(EXIT(ch, door)->exit_info, EX_CLOSED)) send_to_char("It's already open!\r\n", ch); else if (IS_SET(EXIT(ch, door)->exit_info, EX_LOCKED)) send_to_char("It seems to be locked.\r\n", ch); else { REMOVE_BIT(EXIT(ch, door)->exit_info, EX_CLOSED); if (EXIT(ch, door)->keyword) act("$n opens the $F.", FALSE, ch, 0, EXIT(ch, door)->keyword, TO_ROOM); else act("$n opens the door.", FALSE, ch, 0, 0, TO_ROOM); send_to_char(OK, ch); /* now for opening the OTHER side of the door! */ if ((other_room = EXIT(ch, door)->to_room) != NOWHERE) if ((back = world[other_room].dir_option[rev_dir[door]])) if (back->to_room == ch->in_room) { REMOVE_BIT(back->exit_info, EX_CLOSED); if (back->keyword) { sprintf(buf, "The %s is opened from the other side.\r\n", fname(back->keyword)); send_to_room(buf, EXIT(ch, door)->to_room); } else send_to_room("The door is opened from the other side.\r\n", EXIT(ch, door)->to_room); } } } ACMD(do_close) { int door, other_room; char type[MAX_INPUT_LENGTH], dir[MAX_INPUT_LENGTH]; struct room_direction_data *back; struct obj_data *obj; struct char_data *victim; two_arguments(argument, type, dir); if (!*type) send_to_char("Close what?\r\n", ch); else if (generic_find(argument, FIND_OBJ_INV | FIND_OBJ_ROOM, ch, &victim, &obj)) /* this is an object */ if (GET_OBJ_TYPE(obj) != ITEM_CONTAINER) send_to_char("That's not a container.\r\n", ch); else if (IS_SET(GET_OBJ_VAL(obj, 1), CONT_CLOSED)) send_to_char("But it's already closed!\r\n", ch); else if (!IS_SET(GET_OBJ_VAL(obj, 1), CONT_CLOSEABLE)) send_to_char("That's impossible.\r\n", ch); else { SET_BIT(GET_OBJ_VAL(obj, 1), CONT_CLOSED); send_to_char(OK, ch); act("$n closes $p.", FALSE, ch, obj, 0, TO_ROOM); } else if ((door = find_door(ch, type, dir)) >= 0) /* Or a door */ if (!IS_SET(EXIT(ch, door)->exit_info, EX_ISDOOR)) send_to_char("That's absurd.\r\n", ch); else if (IS_SET(EXIT(ch, door)->exit_info, EX_CLOSED)) send_to_char("It's already closed!\r\n", ch); else { SET_BIT(EXIT(ch, door)->exit_info, EX_CLOSED); if (EXIT(ch, door)->keyword) act("$n closes the $F.", 0, ch, 0, EXIT(ch, door)->keyword, TO_ROOM); else act("$n closes the door.", FALSE, ch, 0, 0, TO_ROOM); send_to_char(OK, ch); /* now for closing the other side, too */ if ((other_room = EXIT(ch, door)->to_room) != NOWHERE) if ((back = world[other_room].dir_option[rev_dir[door]])) if (back->to_room == ch->in_room) { SET_BIT(back->exit_info, EX_CLOSED); if (back->keyword) { sprintf(buf, "The %s closes quietly.\r\n", back->keyword); send_to_room(buf, EXIT(ch, door)->to_room); } else send_to_room("The door closes quietly.\r\n", EXIT(ch, door)->to_room); } } } int has_key(struct char_data * ch, int key) { struct obj_data *o; for (o = ch->carrying; o; o = o->next_content) if (GET_OBJ_VNUM(o) == key) return 1; if (ch->equipment[WEAR_HOLD]) if (GET_OBJ_VNUM(ch->equipment[WEAR_HOLD]) == key) return 1; return 0; } ACMD(do_lock) { int door, other_room; char type[MAX_INPUT_LENGTH], dir[MAX_INPUT_LENGTH]; struct room_direction_data *back; struct obj_data *obj; struct char_data *victim; two_arguments(argument, type, dir); if (!*type) send_to_char("Lock what?\r\n", ch); else if (generic_find(argument, FIND_OBJ_INV | FIND_OBJ_ROOM, ch, &victim, &obj)) /* this is an object */ if (GET_OBJ_TYPE(obj) != ITEM_CONTAINER) send_to_char("That's not a container.\r\n", ch); else if (!IS_SET(GET_OBJ_VAL(obj, 1), CONT_CLOSED)) send_to_char("Maybe you should close it first...\r\n", ch); else if (GET_OBJ_VAL(obj, 2) < 0) send_to_char("That thing can't be locked.\r\n", ch); else if (!has_key(ch, GET_OBJ_VAL(obj, 2))) send_to_char("You don't seem to have the proper key.\r\n", ch); else if (IS_SET(GET_OBJ_VAL(obj, 1), CONT_LOCKED)) send_to_char("It is locked already.\r\n", ch); else { SET_BIT(GET_OBJ_VAL(obj, 1), CONT_LOCKED); send_to_char("*Cluck*\r\n", ch); act("$n locks $p - 'cluck', it says.", FALSE, ch, obj, 0, TO_ROOM); } else if ((door = find_door(ch, type, dir)) >= 0) /* a door, perhaps */ if (!IS_SET(EXIT(ch, door)->exit_info, EX_ISDOOR)) send_to_char("That's absurd.\r\n", ch); else if (!IS_SET(EXIT(ch, door)->exit_info, EX_CLOSED)) send_to_char("You have to close it first, I'm afraid.\r\n", ch); else if (EXIT(ch, door)->key < 0) send_to_char("There does not seem to be a keyhole.\r\n", ch); else if (!has_key(ch, EXIT(ch, door)->key) && GET_LEVEL(ch) < LVL_GOD) send_to_char("You don't have the proper key.\r\n", ch); else if (IS_SET(EXIT(ch, door)->exit_info, EX_LOCKED)) send_to_char("It's already locked!\r\n", ch); else { SET_BIT(EXIT(ch, door)->exit_info, EX_LOCKED); if (EXIT(ch, door)->keyword) act("$n locks the $F.", 0, ch, 0, EXIT(ch, door)->keyword, TO_ROOM); else act("$n locks the door.", FALSE, ch, 0, 0, TO_ROOM); send_to_char("*Click*\r\n", ch); /* now for locking the other side, too */ if ((other_room = EXIT(ch, door)->to_room) != NOWHERE) if ((back = world[other_room].dir_option[rev_dir[door]])) if (back->to_room == ch->in_room) SET_BIT(back->exit_info, EX_LOCKED); } } ACMD(do_unlock) { int door, other_room; char type[MAX_INPUT_LENGTH], dir[MAX_INPUT_LENGTH]; struct room_direction_data *back; struct obj_data *obj; struct char_data *victim; two_arguments(argument, type, dir); if (!*type) send_to_char("Unlock what?\r\n", ch); else if (generic_find(argument, FIND_OBJ_INV | FIND_OBJ_ROOM, ch, &victim, &obj)) /* this is an object */ if (GET_OBJ_TYPE(obj) != ITEM_CONTAINER) send_to_char("That's not a container.\r\n", ch); else if (!IS_SET(GET_OBJ_VAL(obj, 1), CONT_CLOSED)) send_to_char("Silly - it ain't even closed!\r\n", ch); else if (GET_OBJ_VAL(obj, 2) < 0) send_to_char("Odd - you can't seem to find a keyhole.\r\n", ch); else if (!has_key(ch, GET_OBJ_VAL(obj, 2))) send_to_char("You don't seem to have the proper key.\r\n", ch); else if (!IS_SET(GET_OBJ_VAL(obj, 1), CONT_LOCKED)) send_to_char("Oh.. it wasn't locked, after all.\r\n", ch); else { REMOVE_BIT(GET_OBJ_VAL(obj, 1), CONT_LOCKED); send_to_char("*Click*\r\n", ch); act("$n unlocks $p.", FALSE, ch, obj, 0, TO_ROOM); } else if ((door = find_door(ch, type, dir)) >= 0) /* it is a door */ if (!IS_SET(EXIT(ch, door)->exit_info, EX_ISDOOR)) send_to_char("That's absurd.\r\n", ch); else if (!IS_SET(EXIT(ch, door)->exit_info, EX_CLOSED)) send_to_char("Heck.. it ain't even closed!\r\n", ch); else if (EXIT(ch, door)->key < 0) send_to_char("You can't seem to spot any keyholes.\r\n", ch); else if (!has_key(ch, EXIT(ch, door)->key) && GET_LEVEL(ch) < LVL_GOD) send_to_char("You do not have the proper key for that.\r\n", ch); else if (!IS_SET(EXIT(ch, door)->exit_info, EX_LOCKED)) send_to_char("It's already unlocked, it seems.\r\n", ch); else { REMOVE_BIT(EXIT(ch, door)->exit_info, EX_LOCKED); if (EXIT(ch, door)->keyword) act("$n unlocks the $F.", 0, ch, 0, EXIT(ch, door)->keyword, TO_ROOM); else act("$n unlocks the door.", FALSE, ch, 0, 0, TO_ROOM); send_to_char("*click*\r\n", ch); /* now for unlocking the other side, too */ if ((other_room = EXIT(ch, door)->to_room) != NOWHERE) if ((back = world[other_room].dir_option[rev_dir[door]])) if (back->to_room == ch->in_room) REMOVE_BIT(back->exit_info, EX_LOCKED); } } ACMD(do_pick) { byte percent; int door, other_room; char type[MAX_INPUT_LENGTH], dir[MAX_INPUT_LENGTH]; struct room_direction_data *back; struct obj_data *obj; struct char_data *v; two_arguments(argument, type, dir); percent = number(1, 101); /* 101% is a complete failure */ if (!*type) send_to_char("Pick what?\r\n", ch); else if (generic_find(argument, FIND_OBJ_INV | FIND_OBJ_ROOM, ch, &v, &obj)) { /* this is an object */ if (GET_OBJ_TYPE(obj) != ITEM_CONTAINER) send_to_char("That's not a container.\r\n", ch); else if (!IS_SET(GET_OBJ_VAL(obj, 1), CONT_CLOSED)) send_to_char("Silly - it isn't even closed!\r\n", ch); else if (GET_OBJ_VAL(obj, 2) < 0) send_to_char("Odd - you can't seem to find a keyhole.\r\n", ch); else if (!IS_SET(GET_OBJ_VAL(obj, 1), CONT_LOCKED)) send_to_char("Oho! This thing is NOT locked!\r\n", ch); else if (IS_SET(GET_OBJ_VAL(obj, 1), CONT_PICKPROOF)) send_to_char("It resists your attempts at picking it.\r\n", ch); else if (percent > GET_SKILL(ch, SKILL_PICK_LOCK)) send_to_char("You failed to pick the lock.\r\n", ch); else { REMOVE_BIT(GET_OBJ_VAL(obj, 1), CONT_LOCKED); send_to_char("*Click*\r\n", ch); act("$n fiddles with $p.", FALSE, ch, obj, 0, TO_ROOM); } } else if ((door = find_door(ch, type, dir)) >= 0) if (!IS_SET(EXIT(ch, door)->exit_info, EX_ISDOOR)) send_to_char("That's absurd.\r\n", ch); else if (!IS_SET(EXIT(ch, door)->exit_info, EX_CLOSED)) send_to_char("You realize that the door is already open.\r\n", ch); else if (EXIT(ch, door)->key < 0) send_to_char("You can't seem to spot any lock to pick.\r\n", ch); else if (!IS_SET(EXIT(ch, door)->exit_info, EX_LOCKED)) send_to_char("Oh.. it wasn't locked at all.\r\n", ch); else if (IS_SET(EXIT(ch, door)->exit_info, EX_PICKPROOF)) send_to_char("You seem to be unable to pick this lock.\r\n", ch); else if (percent > GET_SKILL(ch, SKILL_PICK_LOCK)) send_to_char("You failed to pick the lock.\r\n", ch); else { REMOVE_BIT(EXIT(ch, door)->exit_info, EX_LOCKED); if (EXIT(ch, door)->keyword) act("$n skillfully picks the lock of the $F.", 0, ch, 0, EXIT(ch, door)->keyword, TO_ROOM); else act("$n picks the lock of the door.", TRUE, ch, 0, 0, TO_ROOM); send_to_char("The lock quickly yields to your skills.\r\n", ch); /* now for unlocking the other side, too */ if ((other_room = EXIT(ch, door)->to_room) != NOWHERE) if ((back = world[other_room].dir_option[rev_dir[door]])) if (back->to_room == ch->in_room) REMOVE_BIT(back->exit_info, EX_LOCKED); } } ACMD(do_enter) { int door; one_argument(argument, buf); if (*buf) { /* an argument was supplied, search for door * keyword */ for (door = 0; door < NUM_OF_DIRS; door++) if (EXIT(ch, door)) if (EXIT(ch, door)->keyword) if (!str_cmp(EXIT(ch, door)->keyword, buf)) { perform_move(ch, door, 1); return; } sprintf(buf2, "There is no %s here.\r\n", buf); send_to_char(buf2, ch); } else if (IS_SET(ROOM_FLAGS(ch->in_room), ROOM_INDOORS)) send_to_char("You are already indoors.\r\n", ch); else { /* try to locate an entrance */ for (door = 0; door < NUM_OF_DIRS; door++) if (EXIT(ch, door)) if (EXIT(ch, door)->to_room != NOWHERE) if (!IS_SET(EXIT(ch, door)->exit_info, EX_CLOSED) && IS_SET(ROOM_FLAGS(EXIT(ch, door)->to_room), ROOM_INDOORS)) { perform_move(ch, door, 1); return; } send_to_char("You can't seem to find anything to enter.\r\n", ch); } } ACMD(do_leave) { int door; if (!IS_SET(ROOM_FLAGS(ch->in_room), ROOM_INDOORS)) send_to_char("You are outside.. where do you want to go?\r\n", ch); else { for (door = 0; door < NUM_OF_DIRS; door++) if (EXIT(ch, door)) if (EXIT(ch, door)->to_room != NOWHERE) if (!IS_SET(EXIT(ch, door)->exit_info, EX_CLOSED) && !IS_SET(ROOM_FLAGS(EXIT(ch, door)->to_room), ROOM_INDOORS)) { perform_move(ch, door, 1); return; } send_to_char("I see no obvious exits to the outside.\r\n", ch); } } ACMD(do_stand) { switch (GET_POS(ch)) { case POS_STANDING: act("You are already standing.", FALSE, ch, 0, 0, TO_CHAR); break; case POS_SITTING: act("You stand up.", FALSE, ch, 0, 0, TO_CHAR); act("$n clambers to $s feet.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_STANDING; break; case POS_RESTING: act("You stop resting, and stand up.", FALSE, ch, 0, 0, TO_CHAR); act("$n stops resting, and clambers on $s feet.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_STANDING; break; case POS_SLEEPING: act("You have to wake up first!", FALSE, ch, 0, 0, TO_CHAR); break; case POS_FIGHTING: act("Do you not consider fighting as standing?", FALSE, ch, 0, 0, TO_CHAR); break; default: act("You stop floating around, and put your feet on the ground.", FALSE, ch, 0, 0, TO_CHAR); act("$n stops floating around, and puts $s feet on the ground.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_STANDING; break; } } ACMD(do_sit) { switch (GET_POS(ch)) { case POS_STANDING: act("You sit down.", FALSE, ch, 0, 0, TO_CHAR); act("$n sits down.", FALSE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; break; case POS_SITTING: send_to_char("You're sitting already.\r\n", ch); break; case POS_RESTING: act("You stop resting, and sit up.", FALSE, ch, 0, 0, TO_CHAR); act("$n stops resting.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; break; case POS_SLEEPING: act("You have to wake up first.", FALSE, ch, 0, 0, TO_CHAR); break; case POS_FIGHTING: act("Sit down while fighting? are you MAD?", FALSE, ch, 0, 0, TO_CHAR); break; default: act("You stop floating around, and sit down.", FALSE, ch, 0, 0, TO_CHAR); act("$n stops floating around, and sits down.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; break; } } ACMD(do_rest) { switch (GET_POS(ch)) { case POS_STANDING: act("You sit down and rest your tired bones.", FALSE, ch, 0, 0, TO_CHAR); act("$n sits down and rests.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_RESTING; break; case POS_SITTING: act("You rest your tired bones.", FALSE, ch, 0, 0, TO_CHAR); act("$n rests.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_RESTING; break; case POS_RESTING: act("You are already resting.", FALSE, ch, 0, 0, TO_CHAR); break; case POS_SLEEPING: act("You have to wake up first.", FALSE, ch, 0, 0, TO_CHAR); break; case POS_FIGHTING: act("Rest while fighting? Are you MAD?", FALSE, ch, 0, 0, TO_CHAR); break; default: act("You stop floating around, and stop to rest your tired bones.", FALSE, ch, 0, 0, TO_CHAR); act("$n stops floating around, and rests.", FALSE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; break; } } ACMD(do_sleep) { switch (GET_POS(ch)) { case POS_STANDING: case POS_SITTING: case POS_RESTING: send_to_char("You go to sleep.\r\n", ch); act("$n lies down and falls asleep.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SLEEPING; break; case POS_SLEEPING: send_to_char("You are already sound asleep.\r\n", ch); break; case POS_FIGHTING: send_to_char("Sleep while fighting? Are you MAD?\r\n", ch); break; default: act("You stop floating around, and lie down to sleep.", FALSE, ch, 0, 0, TO_CHAR); act("$n stops floating around, and lie down to sleep.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SLEEPING; break; } } ACMD(do_wake) { struct char_data *vict; int self = 0; one_argument(argument, arg); if (*arg) { if (GET_POS(ch) == POS_SLEEPING) send_to_char("You can't wake people up if you're asleep yourself!\r\n", ch); else if ((vict = get_char_room_vis(ch, arg)) == NULL) send_to_char(NOPERSON, ch); else if (vict == ch) self = 1; else if (GET_POS(vict) > POS_SLEEPING) act("$E is already awake.", FALSE, ch, 0, vict, TO_CHAR); else if (IS_AFFECTED(vict, AFF_SLEEP)) act("You can't wake $M up!", FALSE, ch, 0, vict, TO_CHAR); else { act("You wake $M up.", FALSE, ch, 0, vict, TO_CHAR); act("You are awakened by $n.", FALSE, ch, 0, vict, TO_VICT | TO_SLEEP); GET_POS(vict) = POS_SITTING; } if (!self) return; } if (IS_AFFECTED(ch, AFF_SLEEP)) send_to_char("You can't wake up!\r\n", ch); else if (GET_POS(ch) > POS_SLEEPING) send_to_char("You are already awake...\r\n", ch); else { send_to_char("You awaken, and sit up.\r\n", ch); act("$n awakens.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; } } ACMD(do_follow) { struct char_data *leader; void stop_follower(struct char_data * ch); void add_follower(struct char_data * ch, struct char_data * leader); one_argument(argument, buf); if (*buf) { if (!(leader = get_char_room_vis(ch, buf))) { send_to_char(NOPERSON, ch); return; } } else { send_to_char("Whom do you wish to follow?\r\n", ch); return; } if (ch->master == leader) { act("You are already following $M.", FALSE, ch, 0, leader, TO_CHAR); return; } if (IS_AFFECTED(ch, AFF_CHARM) && (ch->master)) { act("But you only feel like following $N!", FALSE, ch, 0, ch->master, TO_CHAR); } else { /* Not Charmed follow person */ if (leader == ch) { if (!ch->master) { send_to_char("You are already following yourself.\r\n", ch); return; } stop_follower(ch); } else { if (circle_follow(ch, leader)) { act("Sorry, but following in loops is not allowed.", FALSE, ch, 0, 0, TO_CHAR); return; } if (ch->master) stop_follower(ch); REMOVE_BIT(AFF_FLAGS(ch), AFF_GROUP); add_follower(ch, leader); } } }