/* ************************************************************************ * 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 "conf.h" #include "sysdep.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" #include "constants.h" #include "dg_scripts.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 struct index_data *mob_index; /* external functs */ void add_follower(struct char_data *ch, struct char_data *leader); int special(struct char_data *ch, int cmd, char *arg); void death_cry(struct char_data *ch); int find_eq_pos(struct char_data * ch, struct obj_data * obj, char *arg); void do_tracking(struct char_data * ch); /* local functions */ int has_boat(struct char_data *ch); int vehicle_pilot(struct char_data *ch); int can_swim(struct char_data *ch); int find_door(struct char_data *ch, const char *type, char *dir, const char *cmdname); int has_key(struct char_data *ch, obj_vnum key); void do_doorcmd(struct char_data *ch, struct obj_data *obj, int door, int scmd); int ok_pick(struct char_data *ch, obj_vnum keynum, int pickproof, int scmd); int can_fly(struct char_data *ch); ACMD(do_gen_door); ACMD(do_enter); ACMD(do_leave); ACMD(do_stand); ACMD(do_sit); ACMD(do_rest); ACMD(do_sleep); ACMD(do_wake); ACMD(do_follow); ACMD(do_fly); ACMD(do_mount); ACMD(do_dismount); ACMD(do_board); /* simple function to determine if char can walk on water */ int has_boat(struct char_data *ch) { int i; /* if (ROOM_IDENTITY(ch->in_room) == DEAD_SEA) return (1); */ if (GET_LEVEL(ch) > LVL_IMMORT) return (1); if (AFF_FLAGGED(ch, AFF_WATERWALK) || AFF_FLAGGED(ch, AFF_FLY)) return (1); /* Must be sitting in a valid craft for it to work */ if (SITTING_IN(ch)) if ((GET_OBJ_TYPE(SITTING_IN(ch)) == ITEM_BOAT) || (GET_OBJ_TYPE(SITTING_IN(ch)) == ITEM_AIRPLANE)) 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_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_BOAT) return (1); /* If riding a mount perform checks for mount */ if (RIDING(ch)) if (has_boat(RIDING(ch))) return (1); return (0); } /* simple function to determine if char is driving a vehicle */ int vehicle_pilot(struct char_data *ch) { if ((SITTING_IN(ch)) && IS_VEHICLE(SITTING_IN(ch)) && (OBJ_SAT_IN_BY(SITTING_IN(ch)) == ch)) { if (GET_POS(ch) < POS_SITTING) { send_to_char("You're in no position to do anything now.\r\n", ch); return (0); } return (1); } /* Riding is considered riding a vehicle */ if (RIDING(ch) || RIDDEN_BY(ch)) return 1; return (0); } /* simple function to determine if char can fly */ int can_fly(struct char_data *ch) { if (GET_LEVEL(ch) > LVL_IMMORT) return (1); if (AFF_FLAGGED(ch, AFF_FLY)) return (1); /* Must be sitting in a valid craft for it to work */ if (SITTING_IN(ch)) if (GET_OBJ_TYPE(SITTING_IN(ch)) == ITEM_AIRPLANE) return (1); /* If riding a mount perform checks for mount */ if (RIDING(ch)) if (can_fly(RIDING(ch))) return (1); return (0); } /* simple function to determine if char can fly */ int can_swim(struct char_data *ch) { if (GET_LEVEL(ch) > LVL_IMMORT) return (1); if (AFF_FLAGGED(ch, AFF_WATERLUNG)) return (1); /* If riding a mount perform checks for mount */ if (RIDING(ch)) if (can_swim(RIDING(ch))) return (1); return (0); } /* 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) { room_rnum was_in; int need_movement; /* * 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, "")) /* XXX: Evaluate NULL */ return (0); /* charmed? */ if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master && ch->in_room == ch->master->in_room) { if (GET_MOB_VNUM(ch) == 13) { send_to_char("You clack your bones as you become restless.\r\n", ch); act("$n clacks their bones together.", FALSE, ch, 0, 0, TO_ROOM); return (0); } 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 mount, use global direction checks for mount */ if (RIDING(ch)) if ((!CAN_GO(RIDING(ch),dir)) || (!has_boat(RIDING(ch)) && (SECT(EXIT(ch, dir)->to_room) == SECT_WATER_NOSWIM))) { send_to_char("Your mount looks in that direction and shakes it's head.\r\n", ch); return(0); } if (RIDING(ch)) if (SECT(EXIT(ch, dir)->to_room) == SECT_INSIDE) { send_to_char("You probably shouldn't just ride in- maybe dismount first?\r\n", ch); return(0); } if (RIDDEN_BY(ch)) if ((!CAN_GO(ch ,dir)) || (!has_boat(ch) && (SECT(EXIT(ch, dir)->to_room) == SECT_WATER_NOSWIM))) { send_to_char("Your mount looks in that direction and shakes it's head.\r\n", RIDDEN_BY(ch)); return(0); } if (RIDDEN_BY(ch)) if (SECT(EXIT(ch, dir)->to_room) == SECT_INSIDE) { send_to_char("You probably shouldn't just mosey in with someone on your back!\r\n", ch); return(0); } /* Check for dock situations */ if ((SECT(ch->in_room) != SECT_WATER_NOSWIM) && (SECT(EXIT(ch, dir)->to_room) != SECT_WATER_NOSWIM)) { if (SITTING_IN(ch) && (GET_OBJ_TYPE(SITTING_IN(ch)) == ITEM_BOAT) && vehicle_pilot(ch)) { switch (SECT(EXIT(ch, dir)->to_room)) { case SECT_FLYING: send_to_char("Your boat is too heavy to fly.\r\n", ch); break; case SECT_UNDERWATER: send_to_char("Real good, drag your boat underwater!\r\n", ch); break; default: send_to_char("Boats may come to shore but not travel on land!\r\n", ch); break; } return (0); } } /* if this room is up and the air, check for fly spell */ if ((SECT(ch->in_room) == SECT_FLYING) || (SECT(EXIT(ch, dir)->to_room) == SECT_FLYING)) { if ((RIDING(ch)) && (!can_fly(RIDING(ch))) ) { send_to_char("Your mount looks at you and shakes it's head.\r\n", ch); return (0); } else if (!can_fly(ch)) { send_to_char("Your appendages resemble more an arm than a wing!\r\n", ch); return (0); } } /* if ths room is underwater, check for waterlung spell */ if ((SECT(ch->in_room) == SECT_UNDERWATER) || (SECT(EXIT(ch, dir)->to_room) == SECT_UNDERWATER)) { if (!can_swim(ch)) { send_to_char("You have a fish face, but not the gills!\r\n", ch); return (0); } } /* move points needed is avg. move loss for src and destination sect type */ need_movement = (movement_loss[SECT(ch->in_room)] + movement_loss[SECT(EXIT(ch, dir)->to_room)]) / 2; if (GET_POS(ch) == POS_SWIMMING) need_movement = (need_movement * 13); if (RIDING(ch)) { if ((GET_MOVE(RIDING(ch)) < need_movement) && (!IS_NPC(ch))) { send_to_char("Your mount is too exhausted.\r\n", ch); return 0; } } else { 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 (ROOM_FLAGGED(ch->in_room, ROOM_ATRIUM)) { if (!House_can_enter(ch, GET_ROOM_VNUM(EXIT(ch, dir)->to_room))) { send_to_char("That's private property -- no trespassing!\r\n", ch); return (0); } } if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_TUNNEL) && num_pc_in_room(&(world[EXIT(ch, dir)->to_room])) > 1) { send_to_char("There isn't enough room there for more than one person!\r\n", ch); return (0); } /* Mortals and low level gods cannot enter greater god rooms. */ if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_GODROOM) && GET_LEVEL(ch) < LVL_GRGOD) { send_to_char("You aren't godly enough to use that room!\r\n", ch); return (0); } /* see if an entry trigger disallows the move */ if (!entry_mtrigger(ch)) return 0; if (!enter_wtrigger(&world[EXIT(ch, dir)->to_room], ch, dir)) return 0; /* Now we know we're allow to go into the room. */ if (GET_LEVEL(ch) < LVL_IMMORT && !IS_NPC(ch) && !RIDING(ch)) GET_MOVE(ch) -= need_movement; else if (RIDING(ch) && !IS_NPC(ch)) GET_MOVE(RIDING(ch)) -= need_movement; was_in = ch->in_room; /* Positional adustments */ /* Swim if diving into water */ if ((GET_POS(ch) != POS_SWIMMING) && (GET_LEVEL(ch) < LVL_IMMORT) && ((SECT(EXIT(ch, dir)->to_room) == SECT_UNDERWATER) || (SECT(EXIT(ch, dir)->to_room) == SECT_WATER_SWIM) || (SECT(EXIT(ch, dir)->to_room) == SECT_WATER_NOSWIM)) ) { /* Jumping into water? */ if ( (SITTING_IN(ch) == NULL) && (!AFF_FLAGGED(ch, AFF_WATERWALK)) && (!AFF_FLAGGED(ch, AFF_FLY)) ) { GET_POS(ch) = POS_SWIMMING; act("$n jumps head first into the water.", FALSE, ch, 0, 0, TO_ROOM); send_to_char("You jump head first into the water.\r\n", ch); } if (SITTING_IN(ch)) if (SECT(EXIT(ch, dir)->to_room) == SECT_UNDERWATER) { act("$n jumps from $p into the water.", FALSE, ch, SITTING_IN(ch), 0, TO_ROOM); char_from_chair(ch); GET_POS(ch) = POS_SWIMMING; send_to_char("You dive down into the water.\r\n", ch); } } /* Positional adustments */ /* Stand if exiting water */ if ((GET_POS(ch) == POS_SWIMMING) && ((SECT(EXIT(ch, dir)->to_room) != SECT_UNDERWATER) && (SECT(EXIT(ch, dir)->to_room) != SECT_WATER_SWIM) && (SECT(EXIT(ch, dir)->to_room) != SECT_WATER_NOSWIM)) ) { send_to_char("You crawl up out of the water.\r\n", ch); GET_POS(ch) = POS_STANDING; } /* Build entrance and exit messages */ if ( (!IS_AFFECTED(ch, AFF_SNEAK)) && ( (!RIDING(ch)) || (!IS_AFFECTED(RIDING(ch), AFF_SNEAK))) ) { sprintf(buf2, "$n "); /* Type of movement */ /* Vehicle support */ if (SITTING_IN(ch) && vehicle_pilot(ch)) { if (GET_OBJ_TYPE(SITTING_IN(ch)) == ITEM_BOAT) sprintf(buf2 + strlen(buf2), "sails "); else if (GET_OBJ_TYPE(SITTING_IN(ch)) == ITEM_AIRPLANE) sprintf(buf2 + strlen(buf2), "flies "); else if (GET_OBJ_TYPE(SITTING_IN(ch)) == ITEM_WAGON) sprintf(buf2 + strlen(buf2), "rides "); /* Object Name */ sprintf(buf2 + strlen(buf2), "%s ", SITTING_IN(ch)->short_description); } else { /* Positional movement types */ switch (GET_POS(ch)) { case POS_FLYING: sprintf(buf2+ strlen(buf2), "flies "); break; case POS_SWIMMING: sprintf(buf2+ strlen(buf2), "swims "); break; default: if (RIDING(ch)) sprintf(buf2+ strlen(buf2), "rides "); else { if (dg_var_value(ch, "MovementOut") != NULL) sprintf(buf2+ strlen(buf2), "%s ", dg_var_value(ch, "MovementOut")); else sprintf(buf2+ strlen(buf2), "walks "); } break; } /* Mount name? */ if (RIDING(ch)) sprintf(buf2 + strlen(buf2), "%s ", GET_NAME(RIDING(ch))); } /* Direction of travel */ sprintf(buf2 + strlen(buf2), "%s%s.", (dir < UP || dir > DOWN ? "to the " : ""), dirs[dir]); /* Send leaving message */ act(buf2, TRUE, ch, 0, 0, TO_ROOM); } /* Move character */ char_from_room(ch); char_to_room(ch, world[was_in].dir_option[dir]->to_room); /* Build Entrance Message */ if ( (!IS_AFFECTED(ch, AFF_SNEAK)) && ( (!RIDING(ch)) || (!IS_AFFECTED(RIDING(ch), AFF_SNEAK))) ) { sprintf(buf2, "$n "); /* Vehicle Support */ if (SITTING_IN(ch) && vehicle_pilot(ch)) { if (GET_OBJ_TYPE(SITTING_IN(ch)) == ITEM_BOAT) sprintf(buf2 + strlen(buf2), "has sailed in from "); else if (GET_OBJ_TYPE(SITTING_IN(ch)) == ITEM_AIRPLANE) sprintf(buf2 + strlen(buf2), "has flown in from "); else if (GET_OBJ_TYPE(SITTING_IN(ch)) == ITEM_WAGON) sprintf(buf2 + strlen(buf2), "has ridden in from "); } else { /* Positional movement types */ switch (GET_POS(ch)) { case POS_FLYING: sprintf(buf2+ strlen(buf2), "has flown in from "); break; case POS_SWIMMING: sprintf(buf2+ strlen(buf2), "has swam in from "); break; default: if (RIDING(ch)) sprintf(buf2+ strlen(buf2), "has arrived from "); else { if (dg_var_value(ch, "MovementIn") != NULL) sprintf(buf2+ strlen(buf2), "has %s in from ", dg_var_value(ch, "MovementIn")); else sprintf(buf2+ strlen(buf2), "has walked in from "); } break; } } /* Direction of entrance */ sprintf(buf2 + strlen(buf2), "%s%s", (dir < UP || dir > DOWN ? "the " : ""), (dir == UP ? "below": dir == DOWN ? "above" : dirs[rev_dir[dir]])); /* Object Name */ if (SITTING_IN(ch)) sprintf(buf2 + strlen(buf2), " %s %s", sit_types[GET_OBJ_VAL(SITTING_IN(ch), 3)], SITTING_IN(ch)->short_description); /* Mount name */ if (RIDING(ch)) sprintf(buf2 + strlen(buf2), " riding %s", GET_NAME(RIDING(ch))); sprintf(buf2 + strlen(buf2), "."); /* Send arriving message */ act(buf2, TRUE, ch, 0, 0, TO_ROOM); } /* Move vehicle and passengers */ if (SITTING_IN(ch)) move_vehicle(SITTING_IN(ch), world[was_in].dir_option[dir]->to_room); /* Move mount? */ if ( (RIDING(ch)) && (was_in == IN_ROOM(RIDING(ch))) ) { char_from_room(RIDING(ch)); char_to_room(RIDING(ch), IN_ROOM(ch)); } /* Move Rider? */ if ( (RIDDEN_BY(ch)) && (was_in == IN_ROOM(RIDDEN_BY(ch))) ) { char_from_room(RIDDEN_BY(ch)); char_to_room(RIDDEN_BY(ch), IN_ROOM(ch)); } if (ch->desc != NULL) look_at_room(ch, 0); /* If PC is tracking a victim */ if (!IS_NPC(ch) && (HUNTING(ch) != NULL)) do_tracking(ch); if (ROOM_FLAGGED(ch->in_room, ROOM_DEATH) && GET_LEVEL(ch) < LVL_IMMORT) { if (!IS_NPC(ch)) GET_DT_CNT(ch)++; if (RIDING(ch)) { death_cry(RIDING(ch)); extract_char(RIDING(ch)); } if (RIDDEN_BY(ch)) { death_cry(RIDDEN_BY(ch)); extract_char(RIDDEN_BY(ch)); } log_death_trap(ch); death_cry(ch); extract_char(ch); return (0); } entry_memory_mtrigger(ch); if (!greet_mtrigger(ch, dir)) { char_from_room(ch); char_to_room(ch, was_in); look_at_room(ch, 0); } else greet_memory_mtrigger(ch); return (1); } int perform_move(struct char_data *ch, int dir, int need_specials_check) { room_rnum was_in; struct follow_type *k, *next; if (ch == NULL || dir < 0 || dir >= NUM_OF_DIRS) { if (FIGHTING(ch) && (!vehicle_pilot(ch)) ) return (0); } else if (!EXIT(ch, dir) || EXIT(ch, dir)->to_room == NOWHERE || (EXIT_FLAGGED(EXIT(ch, dir), EX_HIDDEN))) send_to_char("Alas, you cannot go that way...\r\n", ch); else if (EXIT_FLAGGED(EXIT(ch, dir), 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); if (SITTING_IN(ch) == NULL) for (k = ch->followers; k; k = next) { next = k->next; if ((k->follower->in_room == 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); } 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, subcmd - 1, 0); } int find_door(struct char_data *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 */ if ((door = search_block(dir, abbr_dirs, FALSE)) == -1) { send_to_char("That's not a direction.\r\n", ch); 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 { sprintf(buf2, "I see no %s there.\r\n", type); send_to_char(buf2, ch); return (-1); } } else return (door); } else { sprintf(buf2, "I really don't see how you can %s anything there.\r\n", cmdname); send_to_char(buf2, ch); return (-1); } } else { /* try to locate the keyword */ if (!*type) { sprintf(buf2, "What is it you want to %s?\r\n", cmdname); send_to_char(buf2, ch); 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); sprintf(buf2, "There doesn't seem to be %s %s here.\r\n", AN(type), type); send_to_char(buf2, ch); return (-1); } } int has_key(struct char_data *ch, obj_vnum key) { struct obj_data *o; for (o = ch->carrying; o; o = o->next_content) if (GET_OBJ_VNUM(o) == key) return (1); if (GET_EQ(ch, WEAR_HOLD)) if (GET_OBJ_VNUM(GET_EQ(ch, WEAR_HOLD)) == key) return (1); return (0); } #define NEED_OPEN (1 << 0) #define NEED_CLOSED (1 << 1) #define NEED_UNLOCKED (1 << 2) #define NEED_LOCKED (1 << 3) 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 }; #define EXITN(room, door) (world[room].dir_option[door]) #define OPEN_DOOR(room, obj, door) ((obj) ?\ (TOGGLE_BIT(GET_OBJ_VAL(obj, 1), CONT_CLOSED)) :\ (TOGGLE_BIT(EXITN(room, door)->exit_info, EX_CLOSED))) #define LOCK_DOOR(room, obj, door) ((obj) ?\ (TOGGLE_BIT(GET_OBJ_VAL(obj, 1), CONT_LOCKED)) :\ (TOGGLE_BIT(EXITN(room, door)->exit_info, EX_LOCKED))) void do_doorcmd(struct char_data *ch, struct obj_data *obj, int door, int scmd) { int other_room = 0; struct room_direction_data *back = 0; sprintf(buf, "$n %ss ", cmd_door[scmd]); if (!obj && ((other_room = EXIT(ch, door)->to_room) != NOWHERE)) if ((back = world[other_room].dir_option[rev_dir[door]]) != NULL) if (back->to_room != ch->in_room) back = 0; switch (scmd) { case SCMD_OPEN: case SCMD_CLOSE: OPEN_DOOR(ch->in_room, obj, door); if (back) OPEN_DOOR(other_room, obj, rev_dir[door]); send_to_char(OK, ch); break; case SCMD_UNLOCK: case SCMD_LOCK: LOCK_DOOR(ch->in_room, obj, door); if (back) LOCK_DOOR(other_room, obj, rev_dir[door]); send_to_char("*Click*\r\n", ch); break; case SCMD_PICK: LOCK_DOOR(ch->in_room, obj, door); if (back) LOCK_DOOR(other_room, obj, rev_dir[door]); send_to_char("The lock quickly yields to your skills.\r\n", ch); strcpy(buf, "$n skillfully picks the lock on "); break; } /* Notify the room */ sprintf(buf + strlen(buf), "%s%s.", ((obj) ? "" : "the "), (obj) ? "$p" : (EXIT(ch, door)->keyword ? "$F" : "door")); if (!(obj) || (obj->in_room != NOWHERE)) act(buf, FALSE, ch, obj, obj ? 0 : EXIT(ch, door)->keyword, TO_ROOM); /* Notify the other room */ if ((scmd == SCMD_OPEN || scmd == SCMD_CLOSE) && back) { sprintf(buf, "The %s is %s%s from the other side.", (back->keyword ? fname(back->keyword) : "door"), cmd_door[scmd], (scmd == SCMD_CLOSE) ? "d" : "ed"); if (world[EXIT(ch, door)->to_room].people) { act(buf, FALSE, world[EXIT(ch, door)->to_room].people, 0, 0, TO_ROOM); act(buf, FALSE, world[EXIT(ch, door)->to_room].people, 0, 0, TO_CHAR); } } } int ok_pick(struct char_data *ch, obj_vnum keynum, int pickproof, int scmd) { int percent; percent = number(1, 101); if (scmd == SCMD_PICK) { if (keynum < 0) send_to_char("Odd - you can't seem to find a keyhole.\r\n", ch); else if (pickproof) send_to_char("It resists your attempts to pick 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 return (1); return (0); } return (1); } #define DOOR_IS_OPENABLE(ch, obj, door) ((obj) ? \ ((GET_OBJ_TYPE(obj) == ITEM_CONTAINER) && \ OBJVAL_FLAGGED(obj, CONT_CLOSEABLE)) :\ (EXIT_FLAGGED(EXIT(ch, door), EX_ISDOOR))) #define DOOR_IS_OPEN(ch, obj, door) ((obj) ? \ (!OBJVAL_FLAGGED(obj, CONT_CLOSED)) :\ (!EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED))) #define DOOR_IS_UNLOCKED(ch, obj, door) ((obj) ? \ (!OBJVAL_FLAGGED(obj, CONT_LOCKED)) :\ (!EXIT_FLAGGED(EXIT(ch, door), EX_LOCKED))) #define DOOR_IS_PICKPROOF(ch, obj, door) ((obj) ? \ (OBJVAL_FLAGGED(obj, CONT_PICKPROOF)) : \ (EXIT_FLAGGED(EXIT(ch, door), EX_PICKPROOF))) #define DOOR_IS_CLOSED(ch, obj, door) (!(DOOR_IS_OPEN(ch, obj, door))) #define DOOR_IS_LOCKED(ch, obj, door) (!(DOOR_IS_UNLOCKED(ch, obj, door))) #define DOOR_KEY(ch, obj, door) ((obj) ? (GET_OBJ_VAL(obj, 2)) : \ (EXIT(ch, door)->key)) #define DOOR_LOCK(ch, obj, door) ((obj) ? (GET_OBJ_VAL(obj, 1)) : \ (EXIT(ch, door)->exit_info)) ACMD(do_gen_door) { int door = -1; obj_vnum keynum; char type[MAX_INPUT_LENGTH], dir[MAX_INPUT_LENGTH]; struct obj_data *obj = NULL; struct char_data *victim = NULL; skip_spaces(&argument); if (!*argument) { sprintf(buf, "%s what?\r\n", cmd_door[subcmd]); send_to_char(CAP(buf), ch); return; } two_arguments(argument, type, dir); if (!generic_find(type, FIND_OBJ_INV | FIND_OBJ_ROOM, ch, &victim, &obj)) door = find_door(ch, type, dir, cmd_door[subcmd]); if ((obj) || (door >= 0)) { keynum = DOOR_KEY(ch, obj, door); if (!(DOOR_IS_OPENABLE(ch, obj, door))) act("You can't $F that!", FALSE, ch, 0, cmd_door[subcmd], TO_CHAR); else if (!DOOR_IS_OPEN(ch, obj, door) && IS_SET(flags_door[subcmd], NEED_OPEN)) send_to_char("But it's already closed!\r\n", ch); else if (!DOOR_IS_CLOSED(ch, obj, door) && IS_SET(flags_door[subcmd], NEED_CLOSED)) send_to_char("But it's currently open!\r\n", ch); else if (!(DOOR_IS_LOCKED(ch, obj, door)) && IS_SET(flags_door[subcmd], NEED_LOCKED)) send_to_char("Oh.. it wasn't locked, after all..\r\n", ch); else if (!(DOOR_IS_UNLOCKED(ch, obj, door)) && IS_SET(flags_door[subcmd], NEED_UNLOCKED)) send_to_char("It seems to be locked.\r\n", ch); else if (!has_key(ch, keynum) && (GET_LEVEL(ch) < LVL_GOD) && ((subcmd == SCMD_LOCK) || (subcmd == SCMD_UNLOCK))) send_to_char("You don't seem to have the proper key.\r\n", ch); else if (ok_pick(ch, keynum, DOOR_IS_PICKPROOF(ch, obj, door), subcmd)) do_doorcmd(ch, obj, door, subcmd); } return; } ACMD(do_enter) { int door; one_argument(argument, buf); if (!strcmp(buf,"water")) { /* Was char sitting in a boat and are they in a water sector? */ if ((SITTING_IN(ch))&&((SECT(ch->in_room) == SECT_WATER_SWIM)||(SECT(ch->in_room) == SECT_WATER_NOSWIM))) { char_from_chair(ch); GET_POS(ch) = POS_SWIMMING; send_to_char("You jump head first into the water.\r\n", ch); act("$n jumps into the water, abandoning $s vessel.", TRUE, ch, 0, 0, TO_ROOM); } /* Are they in the water already? */ else if ((SECT(ch->in_room) == SECT_WATER_SWIM)||(SECT(ch->in_room) == SECT_WATER_NOSWIM)||(SECT(ch->in_room) == SECT_UNDERWATER)) { if (GET_POS(ch) == POS_SWIMMING) { send_to_char("You're already in the water.\r\n", ch); } else { GET_POS(ch) = POS_SWIMMING; send_to_char("You begin swimming arround.\r\n", ch); act("$n enters the water and begins swimming arround.", TRUE, ch, 0, 0, TO_ROOM); } } else { if ( (!SITTING_IN(ch)) || ( (SITTING_IN(ch)) && (GET_OBJ_TYPE(SITTING_IN(ch)) != ITEM_BOAT) ) ) { send_to_char("Maybe you should get on your feet first?\r\n", ch); return; } send_to_char("There is no water here.\r\n", ch); } } else if (*buf) { /* an argument was supplied, search for door * keyword */ if(GET_POS(ch) != POS_STANDING) { send_to_char("Maybe you should get on your feet first?\r\n", ch); return; } 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 (ROOM_FLAGGED(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 (!EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED) && ROOM_FLAGGED(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 (OUTSIDE(ch)) 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 (!EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED) && !ROOM_FLAGGED(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) { if(RIDING(ch)) { send_to_char("Your mount probably wouldn't like you standing on it.\r\n", ch); return;} else if(RIDDEN_BY(ch) && GET_POS(ch)!=POS_STANDING) { send_to_char("It's mighty hard to stand up with someone on your back.\r\n", ch); return;} switch (GET_POS(ch)) { case POS_STANDING: send_to_char("You are already standing.\r\n", ch); break; case POS_SITTING: if((SECT(ch->in_room) == SECT_WATER_NOSWIM) && (!AFF_FLAGGED(ch, AFF_WATERWALK)) ) { send_to_char("Jesus could walk on water, not you!\r\n", ch); break; } if((SECT(ch->in_room) == SECT_WATER_SWIM) && (SITTING_IN(ch))) { send_to_char("Maybe you should enter the water before you go standing up...\r\n", ch); break; } send_to_char("You stand up.\r\n", ch); act("$n clambers to $s feet.", TRUE, ch, 0, 0, TO_ROOM); /* Was char sitting in a chair/vehicle? */ if (SITTING_IN(ch)) char_from_chair(ch); /* 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: if((SECT(ch->in_room) == SECT_WATER_NOSWIM) && (!AFF_FLAGGED(ch, AFF_WATERWALK)) ) { send_to_char("Jesus could walk on water, not you!\r\n", ch); break; } send_to_char("You stop resting, and stand up.\r\n", ch); act("$n stops resting, and clambers on $s feet.", TRUE, ch, 0, 0, TO_ROOM); /* Was char sitting in a chair/vehicle? */ if (SITTING_IN(ch)) char_from_chair(ch); GET_POS(ch) = POS_STANDING; break; case POS_SLEEPING: send_to_char("You have to wake up first!\r\n", ch); break; case POS_FIGHTING: send_to_char("Do you not consider fighting as standing?\r\n", ch); break; case POS_FLYING: if (SECT(ch->in_room) == SECT_FLYING) { send_to_char("If there were something to stand on, maybe!\r\n", ch); break; } send_to_char("You stop flying about, and put your feet on the ground.\r\n",ch); act("$n stops flying about, and puts $s feet on the ground.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_STANDING; break; default: send_to_char("You stop floating around, and put your feet on the ground.\r\n", ch); 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) { struct obj_data *chair = NULL; struct char_data *tempch; int found; if(RIDING(ch)) { send_to_char("You're mounted, what position do you think your in?\r\n", ch); return;} else if(RIDDEN_BY(ch) && GET_POS(ch)!=POS_SITTING) { send_to_char("It's mighty hard to sit down with someone on your back.\r\n", ch); return;} one_argument(argument, arg); if (!*arg) found = 0; if (!(chair = get_obj_in_list_vis(ch, arg, world[ch->in_room].contents))) found = 0; else { found = 1; } switch (GET_POS(ch)) { case POS_STANDING: if (found == 0 ) { send_to_char("You sit down.\r\n", ch); act("$n sits down.", FALSE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; } else { if (!OBJ_FLAGGED(chair, ITEM_SEAT)) { send_to_char("You can't sit in that!\r\n", ch); return; } else if (GET_OBJ_VAL(chair, 1) > GET_OBJ_VAL(chair, 0)) { /* val 1 is current number in chair, 0 is max in chair */ act("$p looks like it's all full.", TRUE, ch, chair, 0, TO_CHAR); sprintf(buf, "SYSERR: chair %d holding too many people.", GET_OBJ_VNUM(chair)); return; } else if (GET_OBJ_VAL(chair, 1) == GET_OBJ_VAL(chair, 0)) { act("There is nowhere left to sit upon $p.", TRUE, ch, chair, 0, TO_CHAR); return; } else { if (OBJ_SAT_IN_BY(chair) == NULL) OBJ_SAT_IN_BY(chair) = ch; for (tempch = OBJ_SAT_IN_BY(chair); tempch != ch ; tempch = NEXT_IN_SEAT(tempch)) { if (NEXT_IN_SEAT(tempch)) continue; NEXT_IN_SEAT(tempch) = ch; } sprintf(buf, "You sit %s %s.\r\n", sit_types[GET_OBJ_VAL(chair, 3)], chair->short_description); send_to_char(buf, ch); if (IS_NPC(ch)) { strcpy(buf, ch->player.short_descr); CAP(buf); } else sprintf(buf, "%s", ch->player.name); sprintf(buf + strlen(buf), " sits %s %s.", sit_types[GET_OBJ_VAL(chair, 3)], chair->short_description); act(buf, FALSE, ch, 0, 0, TO_ROOM); SITTING_IN(ch) = chair; NEXT_IN_SEAT(ch) = NULL; GET_OBJ_VAL(chair, 1) += 1; GET_POS(ch) = POS_SITTING; } } break; case POS_SITTING: send_to_char("You're sitting already.\r\n", ch); break; case POS_RESTING: send_to_char("You stop resting, and sit up.\r\n", ch); act("$n stops resting.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; break; case POS_SLEEPING: send_to_char("You have to wake up first.\r\n", ch); break; case POS_FIGHTING: send_to_char("Sit down while fighting? Are you MAD?\r\n", ch); break; case POS_FLYING: if (SECT(ch->in_room) == SECT_FLYING) { send_to_char("If there were something to sit on, maybe!\r\n", ch); break; } send_to_char("You stop flying about, landing with your rump on the ground.\r\n",ch); act("$n stops flying about, and lands with his $s rump on the ground.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; break; case POS_SWIMMING: send_to_char("You are supposed to swim in water, not sit.\r\n", ch); break; default: send_to_char("You stop floating around, and sit down.\r\n", ch); act("$n stops floating around, and sits down.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; break; } } ACMD(do_rest) { struct obj_data *chair = NULL; struct char_data *tempch; int found; if(RIDING(ch)) { send_to_char("You can't find a comfortable way to rest while mounted.\r\n", ch); return;} else if(RIDDEN_BY(ch) && GET_POS(ch)!=POS_RESTING) { send_to_char("It's mighty hard to rest with someone on your back.\r\n", ch); return;} one_argument(argument, arg); if (!*arg) found = 0; else { if (!(chair = get_obj_in_list_vis(ch, arg, world[ch->in_room].contents))) found = 0; else found = 1; } switch (GET_POS(ch)) { case POS_STANDING: if (found == 0) { send_to_char("You sit down and rest your tired bones.\r\n", ch); act("$n sits down and rests.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_RESTING; } else { if (!OBJ_FLAGGED(chair, ITEM_SEAT)) { send_to_char("You can't sit in that!\r\n", ch); return; } else if (GET_OBJ_VAL(chair, 1) > GET_OBJ_VAL(chair, 0)) { /* val 1 is current number in chair, 0 is max in chair */ act("$p looks like it's all full.", TRUE, ch, chair, 0, TO_CHAR); sprintf(buf, "SYSERR: chair %d holding too many people.", GET_OBJ_VNUM(chair)); return; } else if (GET_OBJ_VAL(chair, 1) == GET_OBJ_VAL(chair, 0)) { act("There is nowhere left to sit upon $p.", TRUE, ch, chair, 0, TO_CHAR); return; } else { if (OBJ_SAT_IN_BY(chair) == NULL) OBJ_SAT_IN_BY(chair) = ch; for (tempch = OBJ_SAT_IN_BY(chair); tempch != ch ; tempch = NEXT_IN_SEAT(tempch)) { if (NEXT_IN_SEAT(tempch)) continue; NEXT_IN_SEAT(tempch) = ch; } sprintf(buf, "You rest your bones %s %s.\r\n", sit_types[GET_OBJ_VAL(chair, 3)], chair->short_description); send_to_char(buf, ch); if (IS_NPC(ch)) { strcpy(buf, ch->player.short_descr); CAP(buf); } else sprintf(buf, "%s", ch->player.name); sprintf(buf + strlen(buf), " rests %s bones %s %s.", HSHR(ch), sit_types[GET_OBJ_VAL(chair, 3)], chair->short_description); act(buf, FALSE, ch, 0, 0, TO_ROOM); SITTING_IN(ch) = chair; NEXT_IN_SEAT(ch) = NULL; GET_OBJ_VAL(chair, 1) = 1; GET_POS(ch) = POS_RESTING; } } break; case POS_SITTING: send_to_char("You rest your tired bones.\r\n", ch); act("$n rests.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_RESTING; break; case POS_RESTING: send_to_char("You are already resting.\r\n", ch); break; case POS_SLEEPING: send_to_char("You have to wake up first.\r\n", ch); break; case POS_FIGHTING: send_to_char("Rest while fighting? Are you MAD?\r\n", ch); break; case POS_SWIMMING: send_to_char("Calgon take me away...\r\n", ch); break; default: send_to_char("You stop floating around, and stop to rest your tired bones.\r\n", ch); act("$n stops floating around, and rests.", FALSE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; break; } } ACMD(do_sleep) { if(RIDING(ch)) { act("You try to sleep on $N and fall right off.", FALSE, ch, 0, RIDING(ch), TO_CHAR); act("$n tries to sleep and falls right off of you.", FALSE, ch, 0, RIDING(ch), TO_VICT); act("$n tries to sleep, but falls right off of $N.", TRUE, ch, 0, RIDING(ch), TO_NOTVICT); dismount_char(ch); GET_POS(ch) = POS_SITTING; return; } else if(RIDDEN_BY(ch) && GET_POS(ch)!=POS_SLEEPING) { send_to_char("It's mighty hard to sleep with someone on your back.\r\n", ch); return;} 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; case POS_FLYING: send_to_char("You stop floating around, and lie down to sleep.\r\n", ch); act("$n stops floating around, and lie down to sleep.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SLEEPING; break; case POS_SWIMMING: send_to_char("Snoring and water don't quite mix!\r\n", ch); break; default: send_to_char("You stop floating around, and lie down to sleep.\r\n", ch); 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; if(RIDING(ch)) { send_to_char("It probably wouldn't be wise sleeping while mounted.\r\n", ch); return; } else if(RIDDEN_BY(ch)) { send_to_char("You wake up to find someone mounted on your back.\r\n", ch); send_to_char("It's struggle to sit up, but slowly and painfuly you do.\r\n", ch); act("$n awakens with a heavy load on his back.", TRUE, ch, 0, 0, TO_ROOM); GET_POS(ch) = POS_SITTING; return; } one_argument(argument, arg); if (*arg) { if (GET_POS(ch) == POS_SLEEPING) send_to_char("Maybe you should wake yourself up first.\r\n", ch); else if ((vict = get_char_vis(ch, arg, FIND_CHAR_ROOM)) == NULL) send_to_char(NOPERSON, ch); 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("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; one_argument(argument, buf); if (*buf) { if (!(leader = get_char_vis(ch, buf, FIND_CHAR_ROOM))) { 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 (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("You are already following yourself.\r\n", ch); return; } stop_follower(ch); } else { if (circle_follow(ch, leader)) { send_to_char("Sorry, but following in loops is not allowed.\r\n", ch); return; } if (ch->master) stop_follower(ch); REMOVE_BIT(AFF_FLAGS(ch), AFF_GROUP); add_follower(ch, leader); } } } ACMD(do_fly) { if (GET_POS(ch) == POS_FLYING) { send_to_char("You are allready flying about.\r\n", ch); return; } if (!AFF_FLAGGED(ch, AFF_FLY)) { send_to_char("You flap your arms but don't rise an inch.\r\n",ch); act("$n flaps his arms like a chicken.", FALSE, ch, 0, 0, TO_ROOM); return; } if (SITTING_IN(ch)) char_from_chair(ch); GET_POS(ch) = POS_FLYING; send_to_char("You rise up into the air with ease.\r\n", ch); act("$n rises up into the air.", FALSE, ch, 0, 0, TO_ROOM); } ACMD(do_mount) { char arg[MAX_INPUT_LENGTH]; struct char_data *vict; one_argument(argument, arg); if (!arg || !*arg) { send_to_char("Mount who?\r\n", ch); return; } else if (!(vict = get_char_room_vis(ch, arg))) { send_to_char("There is no-one by that name here.\r\n", ch); return; } else if (ch == vict) { send_to_char("Don't hurt yourself!\r\n", ch); return; } else if (!IS_NPC(vict) && GET_LEVEL(ch) < LVL_IMMORT) { send_to_char("That's not gonna happen- sorry bud.\r\n", ch); return; } else if (RIDING(ch) || RIDDEN_BY(ch)) { send_to_char("You are already mounted.\r\n", ch); return; } else if (RIDING(vict) || RIDDEN_BY(vict)) { send_to_char("It is already mounted.\r\n", ch); return; } else if (GET_LEVEL(ch) < LVL_IMMORT && IS_NPC(vict) && !MOB_FLAGGED(vict, MOB_MOUNTABLE)) { send_to_char("You can't mount that!\r\n", ch); return; } else if (!IS_NPC(ch) && (!GET_SKILL(ch, SKILL_RIDING))) { send_to_char("First you need to learn *how* to mount.\r\n", ch); return; } else if (!IS_NPC(ch) && (GET_SKILL(ch, SKILL_RIDING) <= number(1, 101))) { act("You try to mount $N, but slip and fall off.", FALSE, ch, 0, vict, TO_CHAR); act("$n tries to mount you, but slips and falls off.", FALSE, ch, 0, vict, TO_VICT); act("$n tries to mount $N, but slips and falls off.", TRUE, ch, 0, vict, TO_NOTVICT); damage(ch, ch, dice(1, 2), -1); return; } act("You mount $N.", FALSE, ch, 0, vict, TO_CHAR); act("$n mounts you.", FALSE, ch, 0, vict, TO_VICT); act("$n mounts $N.", TRUE, ch, 0, vict, TO_NOTVICT); mount_char(ch, vict); GET_POS(ch) = POS_SITTING; } ACMD(do_dismount) { if (!RIDING(ch)) { send_to_char("You aren't even riding anything.\r\n", ch); return; } act("You dismount $N.", FALSE, ch, 0, RIDING(ch), TO_CHAR); act("$n dismounts from you.", FALSE, ch, 0, RIDING(ch), TO_VICT); act("$n dismounts $N.", TRUE, ch, 0, RIDING(ch), TO_NOTVICT); dismount_char(ch); GET_POS(ch) = POS_STANDING; } ACMD(do_board) { struct obj_data *chair = NULL; struct char_data *tempch; int found; if(RIDING(ch)) { send_to_char("Take your mount on a boat? HAH!\r\n", ch); return;} else if(RIDDEN_BY(ch) && GET_POS(ch)!=POS_SITTING) { send_to_char("It's mighty hard to board anything with someone on your back.\r\n", ch); return;} one_argument(argument, arg); if (!*arg) found = 0; if (!(chair = get_obj_in_list_vis(ch, arg, world[ch->in_room].contents))) found = 0; else { found = 1; } switch (GET_POS(ch)) { case POS_STANDING: case POS_SWIMMING: if (found == 0 ) { send_to_char("I don't see that here...\r\n", ch); } else { if (!GET_OBJ_TYPE(chair) == ITEM_BOAT) { send_to_char("That's not a boat!\r\n", ch); return; } else if (!OBJ_FLAGGED(chair, ITEM_SEAT)) { send_to_char("You can't board that!\r\n", ch); return; } else if (GET_OBJ_VAL(chair, 1) > GET_OBJ_VAL(chair, 0)) { /* val 1 is current number in chair, 0 is max in chair */ act("$p looks like it's all full.", TRUE, ch, chair, 0, TO_CHAR); sprintf(buf, "SYSERR: chair %d holding too many people.", GET_OBJ_VNUM(chair)); return; } else if (GET_OBJ_VAL(chair, 1) == GET_OBJ_VAL(chair, 0)) { act("There is no room to board $p.", TRUE, ch, chair, 0, TO_CHAR); return; } else { if (OBJ_SAT_IN_BY(chair) == NULL) OBJ_SAT_IN_BY(chair) = ch; for (tempch = OBJ_SAT_IN_BY(chair); tempch != ch ; tempch = NEXT_IN_SEAT(tempch)) { if (NEXT_IN_SEAT(tempch)) continue; NEXT_IN_SEAT(tempch) = ch; } sprintf(buf, "You board %s.\r\n", chair->short_description); send_to_char(buf, ch); if (IS_NPC(ch)) { strcpy(buf, ch->player.short_descr); CAP(buf); } else sprintf(buf, "%s", ch->player.name); sprintf(buf + strlen(buf), " boards %s.", chair->short_description); act(buf, FALSE, ch, 0, 0, TO_ROOM); SITTING_IN(ch) = chair; NEXT_IN_SEAT(ch) = NULL; GET_OBJ_VAL(chair, 1) += 1; GET_POS(ch) = POS_SITTING; } } break; case POS_SITTING: case POS_RESTING: send_to_char("You're gonna have to stand up to do this.\r\n", ch); break; case POS_SLEEPING: send_to_char("You have to wake up first.\r\n", ch); break; case POS_FIGHTING: send_to_char("Sit down and board a vessel while fighting? Are you MAD?\r\n", ch); break; default: send_to_char("You better get your feet on the ground or your body in the water first!\r\n", ch); break; } }