/**
* @file act_move.c
* @ingroup common
*
* Movement commands, door handling, and sleep/rest/etc state
*
* @author Part of CircleMUD
*
* @par Copyright:
* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University<br>
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.
*
* @par
* All rights reserved. See license.doc for complete information.
*
* @package cs
* @version 1.0
*/
#include "conf.h"
#include "sysdep.h"
#include "structs.h"
#include "utils.h"
#include "character.h"
#include "comm.h"
#include "command.h"
#include "interpreter.h"
#include "handler.h"
#include "db.h"
#include "spells.h"
#include "house.h"
#include "constants.h"
#include "log.h"
#include "base.h"
#include "zone.h"
#include "room.h"
#include "item.h"
/* external variables */
extern int tunnel_size;
/* external functions */
int special(charData_t *ch, const commandData_t *cmd, char *arg);
void death_cry(charData_t *ch);
int find_eq_pos(charData_t *ch, itemData_t *obj, char *arg);
/* local functions */
int has_boat(charData_t *ch);
int find_door(charData_t *ch, const char *type, char *dir, const char *cmdname);
int has_key(charData_t *ch, itemData_t *key);
void do_doorcmd(charData_t *ch, itemData_t *obj, int door, const commandData_t *cmd);
int ok_pick(charData_t *ch, itemData_t *key, int pickproof, const commandData_t *cmd);
/**
* Simple function to determine if char can walk on water
* @param ch Character to check
* @returns TRUE or FALSE
* @todo Update to bool instead of int
*/
int has_boat(charData_t *ch)
{
itemData_t *obj;
int i;
/*
if (ROOM_IDENTITY(IN_ROOM(ch)) == DEAD_SEA)
return (1);
*/
if (GET_AUTH(ch) >= AUTH_WIZARD)
return (1);
if (AFF_FLAGGED(ch, AFF_WATERWALK))
return (1);
/* non-wearable boats in inventory will do it */
for (obj = ch->carrying; obj; obj = obj->nextContent)
if (GET_ITEM_TYPE(obj) == ITEM_BOAT && (find_eq_pos(ch, obj, NULL) < 0))
return (1);
/* and any boat you're wearing will do it too */
for (i = 0; i < NUM_WEARS; i++)
if (GET_EQ(ch, i) && GET_ITEM_TYPE(GET_EQ(ch, i)) == ITEM_BOAT)
return (1);
return (0);
}
/**
* Move a character in a given direction
*
* do_simple_move assumes
* 1. That there is no master and no followers.
* 2. That the direction exists.
*
* @param ch Character to move
* @param dir Direction to move
* @param need_specials_check Should a spec_proc() check be run after the move
* @returns TRUE or FALSE
* @todo Update to bool instead of int
*/
int do_simple_move(charData_t *ch, int dir, int need_specials_check)
{
char throwaway[MAX_INPUT_LENGTH] = ""; /* Functions assume writable. */
roomData_t *was_in;
int need_movement;
const commandData_t *cmd = find_command(dirs[dir]);
/*
* 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, cmd, throwaway))
return (0);
/* charmed? */
if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master && IN_ROOM(ch) == IN_ROOM(ch->master)) {
send_to_char(ch, "The thought of leaving your master makes you weep.\r\n");
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 ((SECT(IN_ROOM(ch)) == SECT_WATER_NOSWIM) ||
(SECT(EXIT(ch, dir)->toRoom) == SECT_WATER_NOSWIM)) {
if (!has_boat(ch)) {
send_to_char(ch, "You need a boat to go there.\r\n");
return (0);
}
}
/* move points needed is avg. move loss for src and destination sect type */
need_movement = (movement_loss[SECT(IN_ROOM(ch))] +
movement_loss[SECT(EXIT(ch, dir)->toRoom)]) / 2;
if (GET_MOVE(ch) < need_movement && !IS_NPC(ch)) {
if (need_specials_check && ch->master)
send_to_char(ch, "You are too exhausted to follow.\r\n");
else
send_to_char(ch, "You are too exhausted.\r\n");
return (0);
}
if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_ATRIUM)) {
if (!House_can_enter(ch, EXIT(ch, dir)->toRoom)) {
send_to_char(ch, "That's private property -- no trespassing!\r\n");
return (0);
}
}
if (ROOM_FLAGGED(EXIT(ch, dir)->toRoom, ROOM_TUNNEL) && num_pc_in_room(EXIT(ch, dir)->toRoom) >= tunnel_size) {
if (tunnel_size > 1)
send_to_char(ch, "There isn't enough room for you to go there!\r\n");
else
send_to_char(ch, "There isn't enough room there for more than one person!\r\n");
return (0);
}
/* Mortals cannot enter wizard rooms. */
if (ROOM_FLAGGED(EXIT(ch, dir)->toRoom, ROOM_WIZROOM) &&
GET_AUTH(ch) < AUTH_WIZARD) {
send_to_char(ch, "You aren't godly enough to use that room!\r\n");
return (0);
}
/* Now we know we're allow to go into the room. */
if (GET_AUTH(ch) < AUTH_WIZARD && !IS_NPC(ch))
GET_MOVE(ch) -= need_movement;
if (!AFF_FLAGGED(ch, AFF_SNEAK)) {
char buf2[MAX_STRING_LENGTH];
snprintf(buf2, sizeof(buf2), "$n leaves %s.", dirs[dir]);
act(buf2, TRUE, ch, 0, 0, TO_ROOM);
}
was_in = IN_ROOM(ch);
char_fromRoom(ch);
char_toRoom(ch, was_in->dir[dir]->toRoom);
if (!AFF_FLAGGED(ch, AFF_SNEAK))
act("$n has arrived.", TRUE, ch, 0, 0, TO_ROOM);
if (ch->desc != NULL)
look_at_room(ch, 0);
if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_DEATH) && GET_AUTH(ch) < AUTH_WIZARD) {
log_death_trap(ch);
death_cry(ch);
char_extract(ch);
return (0);
}
return (1);
}
/**
* Higher level character movement command
*
* This function will check to see if a direction exists and any door which
* might be there is open, and if so passes character to do_simple_move
*
* @param ch Character to move
* @param dir Direction to move
* @param need_specials_check Should a spec_proc() check be run after the move
* @returns TRUE or FALSE
* @todo Update to bool instead of int
*/
int perform_move(charData_t *ch, int dir, int need_specials_check)
{
roomData_t *was_in = NULL;
followData_t *k, *next;
if (ch == NULL || dir < 0 || dir >= NUM_OF_DIRS || FIGHTING(ch))
return (0);
else if (!EXIT(ch, dir) || EXIT(ch, dir)->toRoom == NULL)
send_to_char(ch, "Alas, you cannot go that way...\r\n");
else if (EXIT_FLAGGED(EXIT(ch, dir), EX_CLOSED)) {
if (EXIT(ch, dir)->keyword)
send_to_char(ch, "The %s seems to be closed.\r\n", fname(EXIT(ch, dir)->keyword));
else
send_to_char(ch, "It seems to be closed.\r\n");
} else {
if (!ch->followers)
return (do_simple_move(ch, dir, need_specials_check));
was_in = IN_ROOM(ch);
if (!do_simple_move(ch, dir, need_specials_check))
return (0);
for (k = ch->followers; k; k = next) {
next = k->next;
if ((IN_ROOM(k->follower) == was_in) &&
(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);
}
/**
* MOVE command
*
* This command lets a user move in a stated direction
*
* @param ch the character performing the command
* @param argument the additional text passed after the command
* @param cmd the command object that was performed
* @returns none
* @sa perform_move
*/
ACMD(do_move)
{
if (CMD_IS("north")) perform_move(ch, 0, 0);
else if (CMD_IS("east")) perform_move(ch, 1, 0);
else if (CMD_IS("south")) perform_move(ch, 2, 0);
else if (CMD_IS("west")) perform_move(ch, 3, 0);
else if (CMD_IS("up")) perform_move(ch, 4, 0);
else if (CMD_IS("down")) perform_move(ch, 5, 0);
}
/**
* Find a door by specified keyword/name
*
* @param ch Character looking for a door
* @param type Specified keyword for the door to find
* @param dir A specific direction or NULL
* @param cmdname Text value of the command "open", "unlock", "close", etc
* @returns Numeric value of door if found, or -1
*/
int find_door(charData_t *ch, const char *type, char *dir, const char *cmdname)
{
int door;
if (*dir) { /* a direction was specified */
if ((door = search_block(dir, dirs, FALSE)) == -1) { /* Partial Match */
send_to_char(ch, "That's not a direction.\r\n");
return (-1);
}
if (EXIT(ch, door)) { /* Braces added according to indent. -gg */
if (EXIT(ch, door)->keyword) {
if (isname(type, EXIT(ch, door)->keyword))
return (door);
else {
send_to_char(ch, "I see no %s there.\r\n", type);
return (-1);
}
} else
return (door);
} else {
send_to_char(ch, "I really don't see how you can %s anything there.\r\n", cmdname);
return (-1);
}
} else { /* try to locate the keyword */
if (!*type) {
send_to_char(ch, "What is it you want to %s?\r\n", cmdname);
return (-1);
}
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);
send_to_char(ch, "There doesn't seem to be %s %s here.\r\n", AN(type), type);
return (-1);
}
}
/**
* Check to see if a character has a key object
*
* This function takes a key object in and checks to see if the characater
* has that object in their inventory or equipped. It does /not/ recurse
* through containers.
*
* The key objects are set on exits during boot, pointing to the prototype
* entry for that string vnum (ex: "midgaard:3000")
*
* @param ch Character to check
* @param key Pointer to the key object (prototype)
* @returns TRUE or FALSE
* @todo Update to bool instead of int
*/
int has_key(charData_t *ch, itemData_t *key)
{
itemData_t *o;
for (o = ch->carrying; o; o = o->nextContent)
if (o->prototype == key)
return (1);
if (GET_EQ(ch, WEAR_HOLD))
if (GET_EQ(ch, WEAR_HOLD)->prototype == key)
return (1);
return (0);
}
#define NEED_OPEN BIT_00 /**< Open bit */
#define NEED_CLOSED BIT_01 /**< Closed bit */
#define NEED_UNLOCKED BIT_02 /**< Unlocked bit */
#define NEED_LOCKED BIT_03 /**< Locked bit */
const char *cmd_door[] =
{
"open",
"close",
"unlock",
"lock",
"pick"
};
const int flags_door[] =
{
NEED_CLOSED | NEED_UNLOCKED,
NEED_OPEN,
NEED_CLOSED | NEED_LOCKED,
NEED_CLOSED | NEED_UNLOCKED,
NEED_CLOSED | NEED_LOCKED
};
/**
* Macro to find an exit by number in a room by RNum
*/
#define EXITN(room, door) (room->dir[door])
/**
* Set door open
*/
#define OPEN_DOOR(room, obj, door) ((obj) ?\
(REMOVE_BIT(GET_ITEM_VAL(obj, 1), CONT_CLOSED)) :\
(REMOVE_BIT(EXITN(room, door)->exitInfo, EX_CLOSED)))
/**
* Set door closed
*/
#define CLOSE_DOOR(room, obj, door) ((obj) ?\
(SET_BIT(GET_ITEM_VAL(obj, 1), CONT_CLOSED)) :\
(SET_BIT(EXITN(room, door)->exitInfo, EX_CLOSED)))
/**
* Set door locked
*/
#define LOCK_DOOR(room, obj, door) ((obj) ?\
(SET_BIT(GET_ITEM_VAL(obj, 1), CONT_LOCKED)) :\
(SET_BIT(EXITN(room, door)->exitInfo, EX_LOCKED)))
/**
* Set door unlocked
*/
#define UNLOCK_DOOR(room, obj, door) ((obj) ?\
(REMOVE_BIT(GET_ITEM_VAL(obj, 1), CONT_LOCKED)) :\
(REMOVE_BIT(EXITN(room, door)->exitInfo, EX_LOCKED)))
/**
* Toggle the locked/unlock status of a door
*/
#define TOGGLE_LOCK(room, obj, door) ((obj) ?\
(TOGGLE_BIT(GET_ITEM_VAL(obj, 1), CONT_LOCKED)) :\
(TOGGLE_BIT(EXITN(room, door)->exitInfo, EX_LOCKED)))
/**
* Perform an action on a door. "open", "close", "lock", etc
*
* @param ch Character performing action
* @param obj Item being used in the action or NULL
* @param door Exit number of the door
* @param cmd Numeric value of the command "open", "unlock", "close", etc
* @returns none
*/
void do_doorcmd(charData_t *ch, itemData_t *obj, int door, const commandData_t *cmd)
{
char buf[MAX_STRING_LENGTH];
size_t len;
roomData_t *other_room = NULL;
roomExitData_t *back = NULL;
int dcmd = 0;
if (CMD_IS("open")) dcmd = 0;
else if (CMD_IS("close")) dcmd = 1;
else if (CMD_IS("unlock")) dcmd = 2;
else if (CMD_IS("lock")) dcmd = 3;
else if (CMD_IS("pick")) dcmd = 4;
len = snprintf(buf, sizeof(buf), "$n %ss ", cmd_door[dcmd]);
if (!obj && ((other_room = EXIT(ch, door)->toRoom) != NULL))
if ((back = other_room->dir[rev_dir[door]]) != NULL)
if (back->toRoom != IN_ROOM(ch))
back = NULL;
if (CMD_IS("open")) {
OPEN_DOOR(IN_ROOM(ch), obj, door);
if (back)
OPEN_DOOR(other_room, obj, rev_dir[door]);
send_to_char(ch, "%s", OK);
} else if (CMD_IS("close")) {
CLOSE_DOOR(IN_ROOM(ch), obj, door);
if (back)
CLOSE_DOOR(other_room, obj, rev_dir[door]);
send_to_char(ch, "%s", OK);
} else if (CMD_IS("lock")) {
LOCK_DOOR(IN_ROOM(ch), obj, door);
if (back)
LOCK_DOOR(other_room, obj, rev_dir[door]);
send_to_char(ch, "*Click*\r\n");
} else if (CMD_IS("unlock")) {
UNLOCK_DOOR(IN_ROOM(ch), obj, door);
if (back)
UNLOCK_DOOR(other_room, obj, rev_dir[door]);
send_to_char(ch, "*Click*\r\n");
} else if (CMD_IS("pick")) {
TOGGLE_LOCK(IN_ROOM(ch), obj, door);
if (back)
TOGGLE_LOCK(other_room, obj, rev_dir[door]);
send_to_char(ch, "The lock quickly yields to your skills.\r\n");
len = strlcpy(buf, "$n skillfully picks the lock on ", sizeof(buf));
}
/* Notify the room. */
if (len < sizeof(buf))
snprintf(buf + len, sizeof(buf) - len, "%s%s.",
obj ? "" : "the ", obj ? "$p" : EXIT(ch, door)->keyword ? "$F" : "door");
if (!obj || IN_ROOM(obj) != NULL)
act(buf, FALSE, ch, obj, obj ? 0 : EXIT(ch, door)->keyword, TO_ROOM);
/* Notify the other room */
if (back && (CMD_IS("open") || CMD_IS("close")))
send_to_room(EXIT(ch, door)->toRoom, "The %s is %s%s from the other side.",
back->keyword ? fname(back->keyword) : "door", cmd_door[dcmd],
CMD_IS("close") ? "d" : "ed");
}
/**
* Attempt to pick a lock on a door
* @param ch Character attempting to pick the lock
* @param key Pointer to key prototype or NULL
* @param pickproof Value if the lock is un-pickable. TRUE or FALSE.
* @param cmd Command value, "pick" to run
* @returns TRUE or FALSE
* @todo Update to bool instead of int
*/
int ok_pick(charData_t *ch, itemData_t *key, int pickproof, const commandData_t *cmd)
{
int percent, skill_lvl;
if (!CMD_IS("pick"))
return (1);
percent = rand_number(1, 101);
skill_lvl = GET_SKILL(ch, SKILL_PICK_LOCK) + dex_app_skill[GET_DEX(ch)].p_locks;
if (key == NULL)
send_to_char(ch, "Odd - you can't seem to find a keyhole.\r\n");
else if (pickproof)
send_to_char(ch, "It resists your attempts to pick it.\r\n");
else if (percent > skill_lvl)
send_to_char(ch, "You failed to pick the lock.\r\n");
else
return (1);
return (0);
}
/**
* Check if door can be opened
*/
#define DOOR_IS_OPENABLE(ch, obj, door) ((obj) ? \
((GET_ITEM_TYPE(obj) == ITEM_CONTAINER) && \
ITEMVAL_FLAGGED(obj, CONT_CLOSEABLE)) :\
(EXIT_FLAGGED(EXIT(ch, door), EX_ISDOOR)))
/**
* Check if a door is open
*/
#define DOOR_IS_OPEN(ch, obj, door) ((obj) ? \
(!ITEMVAL_FLAGGED(obj, CONT_CLOSED)) :\
(!EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED)))
/**
* Check if a door is unlocked
*/
#define DOOR_IS_UNLOCKED(ch, obj, door) ((obj) ? \
(!ITEMVAL_FLAGGED(obj, CONT_LOCKED)) :\
(!EXIT_FLAGGED(EXIT(ch, door), EX_LOCKED)))
/**
* Check if a door's lock can be picked
*/
#define DOOR_IS_PICKPROOF(ch, obj, door) ((obj) ? \
(ITEMVAL_FLAGGED(obj, CONT_PICKPROOF)) : \
(EXIT_FLAGGED(EXIT(ch, door), EX_PICKPROOF)))
/**
* Check if a door is closed
*/
#define DOOR_IS_CLOSED(ch, obj, door) (!(DOOR_IS_OPEN(ch, obj, door)))
/**
* Check if a door is locked
*/
#define DOOR_IS_LOCKED(ch, obj, door) (!(DOOR_IS_UNLOCKED(ch, obj, door)))
#define DOOR_KEY(ch, obj, door) ((obj) ? (obj)->key ? (obj)->key : NULL : (EXIT(ch, door)->key))
/**
* OPEN, CLOSE, UNLOCK, LOCK, PICK commands
*
* These commands allow a user to interact with doors
*
* @param ch the character performing the command
* @param argument the additional text passed after the command
* @param cmd the command object that was performed
* @returns none
*/
ACMD(do_gen_door)
{
int door = -1;
char type[MAX_INPUT_LENGTH], dir[MAX_INPUT_LENGTH];
itemData_t *obj = NULL;
charData_t *victim = NULL;
itemData_t *key = NULL;
int doorcmd = 0;
if (CMD_IS("open")) doorcmd = 0;
else if (CMD_IS("close")) doorcmd = 1;
else if (CMD_IS("unlock")) doorcmd = 2;
else if (CMD_IS("lock")) doorcmd = 3;
else if (CMD_IS("pick")) doorcmd = 4;
skip_spaces(&argument);
if (!*argument) {
send_to_char(ch, "%c%s what?\r\n", UPPER(*cmd_door[doorcmd]), cmd_door[doorcmd] + 1);
return;
}
two_arguments(argument, type, dir);
if (!generic_find(type, FIND_ITEM_INV | FIND_ITEM_ROOM, ch, &victim, &obj))
door = find_door(ch, type, dir, cmd_door[doorcmd]);
if ((obj) || (door >= 0)) {
key = DOOR_KEY(ch, obj, door);
if (!(DOOR_IS_OPENABLE(ch, obj, door)))
act("You can't $F that!", FALSE, ch, 0, cmd_door[doorcmd], TO_CHAR);
else if (!DOOR_IS_OPEN(ch, obj, door) &&
IS_SET(flags_door[doorcmd], NEED_OPEN))
send_to_char(ch, "But it's already closed!\r\n");
else if (!DOOR_IS_CLOSED(ch, obj, door) &&
IS_SET(flags_door[doorcmd], NEED_CLOSED))
send_to_char(ch, "But it's currently open!\r\n");
else if (!(DOOR_IS_LOCKED(ch, obj, door)) &&
IS_SET(flags_door[doorcmd], NEED_LOCKED))
send_to_char(ch, "Oh.. it wasn't locked, after all..\r\n");
else if (!(DOOR_IS_UNLOCKED(ch, obj, door)) &&
IS_SET(flags_door[doorcmd], NEED_UNLOCKED))
send_to_char(ch, "It seems to be locked.\r\n");
else if (!has_key(ch, key) && GET_AUTH(ch) < AUTH_WIZARD &&
((CMD_IS("lock")) || (CMD_IS("unlock"))))
send_to_char(ch, "You don't seem to have the proper key.\r\n");
else if (ok_pick(ch, key, DOOR_IS_PICKPROOF(ch, obj, door), cmd))
do_doorcmd(ch, obj, door, cmd);
}
return;
}
/**
* ENTER command
*
* This command lets a user enter through a door
*
* @param ch the character performing the command
* @param argument the additional text passed after the command
* @param cmd the command object that was performed
* @returns none
*/
ACMD(do_enter)
{
char buf[MAX_INPUT_LENGTH];
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;
}
send_to_char(ch, "There is no %s here.\r\n", buf);
} else if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_INDOORS))
send_to_char(ch, "You are already indoors.\r\n");
else {
/* try to locate an entrance */
for (door = 0; door < NUM_OF_DIRS; door++)
if (EXIT(ch, door))
if (EXIT(ch, door)->toRoom != NULL)
if (!EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED) &&
ROOM_FLAGGED(EXIT(ch, door)->toRoom, ROOM_INDOORS)) {
perform_move(ch, door, 1);
return;
}
send_to_char(ch, "You can't seem to find anything to enter.\r\n");
}
}
/**
* LEAVE command
*
* This command lets a user leave through a door
*
* @param ch the character performing the command
* @param argument the additional text passed after the command
* @param cmd the command object that was performed
* @returns none
*/
ACMD(do_leave)
{
int door;
if (OUTSIDE(ch))
send_to_char(ch, "You are outside.. where do you want to go?\r\n");
else {
for (door = 0; door < NUM_OF_DIRS; door++)
if (EXIT(ch, door))
if (EXIT(ch, door)->toRoom != NULL)
if (!EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED) &&
!ROOM_FLAGGED(EXIT(ch, door)->toRoom, ROOM_INDOORS)) {
perform_move(ch, door, 1);
return;
}
send_to_char(ch, "I see no obvious exits to the outside.\r\n");
}
}
/**
* STAND command
*
* This command lets a user stand up
*
* @param ch the character performing the command
* @param argument the additional text passed after the command
* @param cmd the command object that was performed
* @returns none
*/
ACMD(do_stand)
{
switch (GET_POS(ch)) {
case POS_STANDING:
send_to_char(ch, "You are already standing.\r\n");
break;
case POS_SITTING:
send_to_char(ch, "You stand up.\r\n");
act("$n clambers to $s feet.", TRUE, ch, 0, 0, TO_ROOM);
/* Will be sitting after a successful bash and may still be fighting. */
GET_POS(ch) = FIGHTING(ch) ? POS_FIGHTING : POS_STANDING;
break;
case POS_RESTING:
send_to_char(ch, "You stop resting, and stand up.\r\n");
act("$n stops resting, and clambers on $s feet.", TRUE, ch, 0, 0, TO_ROOM);
GET_POS(ch) = POS_STANDING;
break;
case POS_SLEEPING:
send_to_char(ch, "You have to wake up first!\r\n");
break;
case POS_FIGHTING:
send_to_char(ch, "Do you not consider fighting as standing?\r\n");
break;
default:
send_to_char(ch, "You stop floating around, and put your feet on the ground.\r\n");
act("$n stops floating around, and puts $s feet on the ground.",
TRUE, ch, 0, 0, TO_ROOM);
GET_POS(ch) = POS_STANDING;
break;
}
}
/**
* SIT command
*
* This command lets a user sit down
*
* @param ch the character performing the command
* @param argument the additional text passed after the command
* @param cmd the command object that was performed
* @returns none
*/
ACMD(do_sit)
{
switch (GET_POS(ch)) {
case POS_STANDING:
send_to_char(ch, "You sit down.\r\n");
act("$n sits down.", FALSE, ch, 0, 0, TO_ROOM);
GET_POS(ch) = POS_SITTING;
break;
case POS_SITTING:
send_to_char(ch, "You're sitting already.\r\n");
break;
case POS_RESTING:
send_to_char(ch, "You stop resting, and sit up.\r\n");
act("$n stops resting.", TRUE, ch, 0, 0, TO_ROOM);
GET_POS(ch) = POS_SITTING;
break;
case POS_SLEEPING:
send_to_char(ch, "You have to wake up first.\r\n");
break;
case POS_FIGHTING:
send_to_char(ch, "Sit down while fighting? Are you MAD?\r\n");
break;
default:
send_to_char(ch, "You stop floating around, and sit down.\r\n");
act("$n stops floating around, and sits down.", TRUE, ch, 0, 0, TO_ROOM);
GET_POS(ch) = POS_SITTING;
break;
}
}
/**
* REST command
*
* This command lets a user rest
*
* @param ch the character performing the command
* @param argument the additional text passed after the command
* @param cmd the command object that was performed
* @returns none
*/
ACMD(do_rest)
{
switch (GET_POS(ch)) {
case POS_STANDING:
send_to_char(ch, "You sit down and rest your tired bones.\r\n");
act("$n sits down and rests.", TRUE, ch, 0, 0, TO_ROOM);
GET_POS(ch) = POS_RESTING;
break;
case POS_SITTING:
send_to_char(ch, "You rest your tired bones.\r\n");
act("$n rests.", TRUE, ch, 0, 0, TO_ROOM);
GET_POS(ch) = POS_RESTING;
break;
case POS_RESTING:
send_to_char(ch, "You are already resting.\r\n");
break;
case POS_SLEEPING:
send_to_char(ch, "You have to wake up first.\r\n");
break;
case POS_FIGHTING:
send_to_char(ch, "Rest while fighting? Are you MAD?\r\n");
break;
default:
send_to_char(ch, "You stop floating around, and stop to rest your tired bones.\r\n");
act("$n stops floating around, and rests.", FALSE, ch, 0, 0, TO_ROOM);
GET_POS(ch) = POS_SITTING;
break;
}
}
/**
* SLEEP command
*
* This command lets a user sleep
*
* @param ch the character performing the command
* @param argument the additional text passed after the command
* @param cmd the command object that was performed
* @returns none
*/
ACMD(do_sleep)
{
switch (GET_POS(ch)) {
case POS_STANDING:
case POS_SITTING:
case POS_RESTING:
send_to_char(ch, "You go to sleep.\r\n");
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(ch, "You are already sound asleep.\r\n");
break;
case POS_FIGHTING:
send_to_char(ch, "Sleep while fighting? Are you MAD?\r\n");
break;
default:
send_to_char(ch, "You stop floating around, and lie down to sleep.\r\n");
act("$n stops floating around, and lie down to sleep.",
TRUE, ch, 0, 0, TO_ROOM);
GET_POS(ch) = POS_SLEEPING;
break;
}
}
/**
* WAKE command
*
* This command lets a user wake up
*
* @param ch the character performing the command
* @param argument the additional text passed after the command
* @param cmd the command object that was performed
* @returns none
*/
ACMD(do_wake)
{
char arg[MAX_INPUT_LENGTH];
charData_t *vict;
int self = 0;
one_argument(argument, arg);
if (*arg) {
if (GET_POS(ch) == POS_SLEEPING)
send_to_char(ch, "Maybe you should wake yourself up first.\r\n");
else if ((vict = get_char_vis(ch, arg, NULL, FIND_CHAR_ROOM)) == NULL)
send_to_char(ch, "%s", NOPERSON);
else if (vict == ch)
self = 1;
else if (AWAKE(vict))
act("$E is already awake.", FALSE, ch, 0, vict, TO_CHAR);
else if (AFF_FLAGGED(vict, AFF_SLEEP))
act("You can't wake $M up!", FALSE, ch, 0, vict, TO_CHAR);
else if (GET_POS(vict) < POS_SLEEPING)
act("$E's in pretty bad shape!", 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 (AFF_FLAGGED(ch, AFF_SLEEP))
send_to_char(ch, "You can't wake up!\r\n");
else if (GET_POS(ch) > POS_SLEEPING)
send_to_char(ch, "You are already awake...\r\n");
else {
send_to_char(ch, "You awaken, and sit up.\r\n");
act("$n awakens.", TRUE, ch, 0, 0, TO_ROOM);
GET_POS(ch) = POS_SITTING;
}
}
/**
* FOLLOW command
*
* This command lets a user follow another character
*
* @param ch the character performing the command
* @param argument the additional text passed after the command
* @param cmd the command object that was performed
* @returns none
*/
ACMD(do_follow)
{
char buf[MAX_INPUT_LENGTH];
charData_t *leader;
one_argument(argument, buf);
if (*buf) {
if (!(leader = get_char_vis(ch, buf, NULL, FIND_CHAR_ROOM))) {
send_to_char(ch, "%s", NOPERSON);
return;
}
} else {
send_to_char(ch, "Whom do you wish to follow?\r\n");
return;
}
if (ch->master == leader) {
act("You are already following $M.", FALSE, ch, 0, leader, TO_CHAR);
return;
}
if (AFF_FLAGGED(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(ch, "You are already following yourself.\r\n");
return;
}
stop_follower(ch);
} else {
if (circle_follow(ch, leader)) {
send_to_char(ch, "Sorry, but following in loops is not allowed.\r\n");
return;
}
if (ch->master)
stop_follower(ch);
REMOVE_BIT(AFF_FLAGS(ch), AFF_GROUP);
add_follower(ch, leader);
}
}
}