//*****************************************************************************
//
// movement.c
//
// all of the functions assocciated with moving (chars and objects)
//
//*****************************************************************************
#include "mud.h"
#include "utils.h"
#include "character.h"
#include "world.h"
#include "zone.h"
#include "room.h"
#include "exit.h"
#include "handler.h"
#include "inform.h"
#include "object.h"
#include "movement.h"
#include "hooks.h"
//*****************************************************************************
// mandatory modules
//*****************************************************************************
#include "items/items.h"
#include "items/furniture.h"
//*****************************************************************************
// implementation of movement.h
//*****************************************************************************
EXIT_DATA *try_move_mssg(CHAR_DATA *ch, const char *dir) {
ROOM_DATA *old_room = charGetRoom(ch);
EXIT_DATA *exit = try_move(ch, dir);
// did we successfully move?
if(exit != NULL) {
ROOM_DATA *new_room = charGetRoom(ch);
int dirnum = dirGetNum(dir);
// are we using an abbreviated direction name?
if(dirnum == DIR_NONE && !roomGetExit(old_room, dir))
dirnum = dirGetAbbrevNum(dir);
// now, we have to temporarily go back to the old room so we can do
// leave messages. Then we come back to the new room and do enter messages
char_from_room(ch);
char_to_room(ch, old_room);
if(*exitGetSpecLeave(exit))
message(ch, NULL, NULL, NULL, TRUE, TO_ROOM, exitGetSpecLeave(exit));
else if(dirnum == DIR_NONE)
send_around_char(ch, TRUE, "%s leaves.\r\n", charGetName(ch));
else
send_around_char(ch, TRUE, "%s leaves %s.\r\n", charGetName(ch),
dirGetName(dirnum));
char_from_room(ch);
char_to_room(ch, new_room);
// do we have a special enter message? If so, use them
if(*exitGetSpecEnter(exit))
message(ch, NULL, NULL, NULL, FALSE, TO_ROOM, exitGetSpecEnter(exit));
else if(dirnum == DIR_NONE)
send_around_char(ch, TRUE, "%s has arrived.\r\n", charGetName(ch));
else
send_around_char(ch, TRUE, "%s arrives from the %s.\r\n",
charGetName(ch), dirGetName(dirGetOpposite(dirnum)));
}
return exit;
}
EXIT_DATA *try_move(CHAR_DATA *ch, const char *dir) {
EXIT_DATA *exit = roomGetExit(charGetRoom(ch), dir);
ROOM_DATA *to = NULL;
// are we using an abbreviated direction name?
if(exit == NULL && dirGetAbbrevNum(dir) != DIR_NONE) {
dir = dirGetName(dirGetAbbrevNum(dir));
exit = roomGetExit(charGetRoom(ch), dir);
}
// did we find an exit?
if(exit == NULL || !can_see_exit(ch, exit))
send_to_char(ch, "{gAlas, there is no exit in that direction.\r\n");
else if(exitIsClosed(exit))
send_to_char(ch, "You will have to open %s first.\r\n",
(*exitGetName(exit) ? exitGetName(exit) : "it"));
else if((to = worldGetRoom(gameworld, exitGetTo(exit))) == NULL)
send_to_char(ch, "It doesn't look like %s leads anywhere!",
(*exitGetName(exit) ? exitGetName(exit) : "it"));
else {
ROOM_DATA *old_room = charGetRoom(ch);
// try all of our exit hooks
hookRun("exit", ch, old_room, exit);
char_from_room(ch);
char_to_room(ch, to);
look_at_room(ch, charGetRoom(ch));
// now try all of our entrance hooks
hookRun("enter", ch, to);
return exit;
}
// our exit failed
return NULL;
}
//
// cmd_move is the basic entry into all of the movement utilities. See
// try_move() in movement.h
COMMAND(cmd_move) {
try_move_mssg(ch, cmd);
}
//*****************************************************************************
// Functions and commands for changing position (sleeping, standing, etc)
//*****************************************************************************
bool try_change_pos(CHAR_DATA *ch, int pos) {
if(charGetPos(ch) == pos) {
send_to_char(ch, "You are already %s.\r\n", posGetName(pos));
return FALSE;
}
else {
send_to_char(ch, "You %s.\r\n", posGetActionSelf(pos));
send_around_char(ch, TRUE, "%s %s.\r\n",
charGetName(ch), posGetActionOther(pos));
charSetPos(ch, pos);
return TRUE;
}
}
bool try_use_furniture(CHAR_DATA *ch, char *arg, int pos) {
// strip out "at" and "on". People might be
// trying "sit at table" or "sleep on bed"
strip_word(arg, "at");
strip_word(arg, "on");
OBJ_DATA *furniture = generic_find(ch, arg,
FIND_TYPE_OBJ,
FIND_SCOPE_ROOM | FIND_SCOPE_VISIBLE,
FALSE, NULL);
if(furniture == NULL)
send_to_char(ch, "Where did you want to %s?\r\n", posGetActionSelf(pos));
else if(!objIsType(furniture, "furniture"))
send_to_char(ch, "But that's not furniture!\r\n");
// make sure we found something we might be able to sit on
else if(charGetFurniture(ch) == furniture)
send_to_char(ch, "You're already %s %s.\r\n",
(furnitureGetType(furniture) == FURNITURE_ON ? "on" : "at"),
objGetName(furniture));
else if(furnitureGetCapacity(furniture) <= listSize(objGetUsers(furniture)))
send_to_char(ch, "There isn't any room left.\r\n");
else {
// if we're already sitting on something, get up first
if(charGetFurniture(ch)) {
send_to_char(ch, "You stand up from %s.\r\n",
objGetName(charGetFurniture(ch)));
message(ch, NULL, charGetFurniture(ch), NULL,TRUE, TO_ROOM,
"$n stands up from $o.");
char_from_furniture(ch);
}
// send out messages
char other_buf[SMALL_BUFFER];
sprintf(other_buf, "$n %s %s $o.",
posGetActionOther(pos),
(furnitureGetType(furniture) == FURNITURE_ON ? "on" : "at"));
message(ch, NULL, furniture, NULL, TRUE, TO_ROOM, other_buf);
send_to_char(ch, "You %s %s %s.\r\n",
posGetActionSelf(pos),
(furnitureGetType(furniture) == FURNITURE_ON ? "on" : "at"),
objGetName(furniture));
// now sit down on the new thing
char_to_furniture(ch, furniture);
charSetPos(ch, pos);
return TRUE;
}
return FALSE;
}
COMMAND(cmd_sit) {
if(!arg || !*arg)
try_change_pos(ch, POS_SITTING);
else
try_use_furniture(ch, arg, POS_SITTING);
}
COMMAND(cmd_sleep) {
if(!arg || !*arg)
try_change_pos(ch, POS_SLEEPING);
else
try_use_furniture(ch, arg, POS_SLEEPING);
}
COMMAND(cmd_stand) {
if(charGetPos(ch) == POS_FLYING) {
send_to_char(ch, "You stop flying.\r\n");
send_around_char(ch, TRUE, "%s stops flying.\r\n", charGetName(ch));
charSetPos(ch, POS_STANDING);
}
else {
if(try_change_pos(ch, POS_STANDING) && charGetFurniture(ch))
char_from_furniture(ch);
}
}
COMMAND(cmd_wake) {
send_to_char(ch, "You stop sleeping and sit up.\r\n");
send_around_char(ch, TRUE, "%s stops sleeping and sits up.\r\n",
charGetName(ch));
charSetPos(ch, POS_SITTING);
}