/* ************************************************************************
* File: ships.c EmpireMUD AD 1.0 *
* Usage: code related to boating *
* *
* All rights reserved. See license.doc for complete information. *
* *
* Code base by Paul Clarke. EmpireMUD Project, a tbgMUD Production. *
* Based upon CircleMUD 3.0, beta patch level 17, by Jeremy Elson. *
* *
* 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 "skills.h"
#include "vnums.h"
#include "empire.h"
/* externs */
extern const char *dirs[];
extern const int room_capacity[];
extern const int building_capacity[];
extern int rev_dir[];
extern int last_action_rotation;
void create_exit(room_rnum from, room_rnum to, int dir, bool back) {
CREATE(world[from].dir_option[dir], struct room_direction_data, 1);
world[from].dir_option[dir]->to_room = to;
world[from].dir_option[dir]->exit_info = 0;
world[from].dir_option[dir]->keyword = NULL;
if (back) {
CREATE(world[to].dir_option[rev_dir[dir]], struct room_direction_data, 1);
world[to].dir_option[rev_dir[dir]]->to_room = from;
world[to].dir_option[rev_dir[dir]]->exit_info = 0;
world[to].dir_option[rev_dir[dir]]->keyword = NULL;
}
}
Object setup_ship_object(obj_vnum vnum, room_rnum main_room) {
Object obj;
obj = read_object(vnum, VIRTUAL);
GET_OBJ_VAL(obj, 2) = world[main_room].number;
return obj;
}
#define SHIP_PINNACE 0
#define SHIP_GALLEY 1
#define SHIP_BRIGANTINE 2
#define SHIP_ARGOSY 3
#define SHIP_GALLEON 4
Object create_ship(obj_vnum vnum, long owner, room_rnum to_room) {
extern room_rnum create_room(room_vnum vnum);
extern room_vnum find_free_vnum(void);
Object ship;
room_rnum main_room;
room_rnum spare[8];
int type, i;
for (i = 0; i < 8; i++)
spare[i] = NOWHERE;
ship = read_object(vnum, VIRTUAL);
type = GET_OBJ_VAL(ship, 0);
/* The main room */
main_room = create_room(find_free_vnum());
GET_OBJ_VAL(ship, 2) = world[main_room].number;
world[main_room].owner = owner;
SECT(main_room) = SECT_INSIDE;
world[main_room].home_room = NOWHERE;
world[main_room].type = RTYPE_B_ONDECK;
world[main_room].boat = ship;
switch (type) {
case SHIP_PINNACE:
/* Helm - 0 */
spare[0] = create_room(find_free_vnum());
world[spare[0]].owner = owner;
world[spare[0]].home_room = main_room;
SECT(spare[0]) = SECT_INSIDE;
world[spare[0]].type = RTYPE_B_HELM;
create_exit(main_room, spare[0], EAST, TRUE);
break;
case SHIP_GALLEY:
/* Helm - 0 */
spare[0] = create_room(find_free_vnum());
world[spare[0]].owner = owner;
world[spare[0]].home_room = main_room;
SECT(spare[0]) = SECT_INSIDE;
world[spare[0]].type = RTYPE_B_HELM;
/* On Deck - 1 */
spare[1] = create_room(find_free_vnum());
world[spare[1]].owner = owner;
world[spare[1]].home_room = main_room;
SECT(spare[1]) = SECT_INSIDE;
world[spare[1]].type = RTYPE_B_ONDECK;
create_exit(main_room, spare[0], EAST, TRUE);
create_exit(main_room, spare[1], WEST, TRUE);
break;
case SHIP_BRIGANTINE:
/* Helm - 0 */
spare[0] = create_room(find_free_vnum());
world[spare[0]].owner = owner;
world[spare[0]].home_room = main_room;
SECT(spare[0]) = SECT_INSIDE;
world[spare[0]].type = RTYPE_B_HELM;
/* Storage - 1 */
spare[1] = create_room(find_free_vnum());
world[spare[1]].owner = owner;
world[spare[1]].home_room = main_room;
SECT(spare[1]) = SECT_INSIDE;
world[spare[1]].type = RTYPE_B_STORAGE;
create_exit(main_room, spare[0], EAST, TRUE);
create_exit(main_room, spare[1], DOWN, TRUE);
break;
case SHIP_ARGOSY:
/* Helm - 0 */
spare[0] = create_room(find_free_vnum());
world[spare[0]].owner = owner;
world[spare[0]].home_room = main_room;
SECT(spare[0]) = SECT_INSIDE;
world[spare[0]].type = RTYPE_B_HELM;
/* On Deck - 1 */
spare[1] = create_room(find_free_vnum());
world[spare[1]].owner = owner;
world[spare[1]].home_room = main_room;
SECT(spare[1]) = SECT_INSIDE;
world[spare[1]].type = RTYPE_B_ONDECK;
/* Storage - 2-3 */
for (i = 2; i <= 3; i++) {
spare[i] = create_room(find_free_vnum());
world[spare[i]].owner = owner;
world[spare[i]].home_room = main_room;
SECT(spare[i]) = SECT_INSIDE;
world[spare[i]].type = RTYPE_B_STORAGE;
}
create_exit(main_room, spare[0], EAST, TRUE);
create_exit(main_room, spare[1], WEST, TRUE);
create_exit(spare[1], spare[2], DOWN, TRUE);
create_exit(main_room, spare[3], DOWN, TRUE);
break;
case SHIP_GALLEON:
/* Helm - 0 */
spare[0] = create_room(find_free_vnum());
world[spare[0]].owner = owner;
world[spare[0]].home_room = main_room;
SECT(spare[0]) = SECT_INSIDE;
world[spare[0]].type = RTYPE_B_HELM;
/* On Deck - 1 */
spare[1] = create_room(find_free_vnum());
world[spare[1]].owner = owner;
world[spare[1]].home_room = main_room;
SECT(spare[1]) = SECT_INSIDE;
world[spare[1]].type = RTYPE_B_ONDECK;
/* Below Deck - 2-3 */
for (i = 2; i <= 3; i++) {
spare[i] = create_room(find_free_vnum());
world[spare[i]].owner = owner;
world[spare[i]].home_room = main_room;
SECT(spare[i]) = SECT_INSIDE;
world[spare[i]].type = RTYPE_B_BELOWDECK;
}
/* Storage - 4-7 */
for (i = 4; i < 8; i++) {
spare[i] = create_room(find_free_vnum());
world[spare[i]].owner = owner;
world[spare[i]].home_room = main_room;
SECT(spare[i]) = SECT_INSIDE;
world[spare[i]].type = RTYPE_B_STORAGE;
}
create_exit(main_room, spare[0], EAST, TRUE);
create_exit(main_room, spare[1], WEST, TRUE);
create_exit(spare[1], spare[2], DOWN, TRUE);
create_exit(spare[2], spare[3], EAST, TRUE);
create_exit(spare[2], spare[4], NORTH, TRUE);
create_exit(spare[2], spare[5], SOUTH, TRUE);
create_exit(spare[3], spare[6], NORTH, TRUE);
create_exit(spare[3], spare[7], SOUTH, TRUE);
break;
default:
extract_obj(ship);
return NULL;
}
/* Load all the important objects */
obj_to_room(setup_ship_object(os_WINDOW, main_room), main_room);
for (i = 0; i < 8; i++)
if (spare[i] != NOWHERE)
switch (world[spare[i]].type) {
case RTYPE_B_HELM:
obj_to_room(setup_ship_object(os_HELM, main_room), spare[i]);
default:
obj_to_room(setup_ship_object(os_WINDOW, main_room), spare[i]);
break;
}
obj_to_room(ship, to_room);
return (ship);
}
ACMD(do_sail) {
extern const char *from_dir[];
Object obj, ship;
int dir;
room_rnum to_room;
skip_spaces(&argument);
if (!(obj = get_obj_in_list_num(real_object(os_HELM), world[ch->in_room].contents)))
msg_to_char(ch, "You can't sail from here.\r\n");
else if (!(ship = world[HOME_ROOM(obj->in_room)].boat))
msg_to_char(ch, "Unable to find a ship associated with this helm!\r\n");
else if (!CAN_USE_ROOM(ch, HOME_ROOM(ch->in_room), 1) && ww_dice(GET_DEXTERITY(ch) + GET_LARCENY(ch), 7) <= 0)
msg_to_char(ch, "You don't have permission to sail this ship.\r\n");
else if (!*argument)
msg_to_char(ch, "Which direction would you like to sail?\r\n");
else if ((dir = parse_direction(argument)) < 0)
msg_to_char(ch, "You can't sail that direction.\r\n");
else if (dir == UP || dir == DOWN)
msg_to_char(ch, "How would that work?\r\n");
else if (SECT(ship->in_room) == SECT_BUILDING) {
if (!world[ship->in_room].dir_option[dir]) {
msg_to_char(ch, "You can't sail that way!\r\n");
return;
}
to_room = world[ship->in_room].dir_option[dir]->to_room;
if (SECT(to_room) != SECT_OCEAN && SECT(to_room) != SECT_RIVER && (SECT(to_room) != SECT_ROAD || !IS_COMPLETE(to_room) || !world[to_room].type))
msg_to_char(ch, "You can't sail that way!\r\n");
else {
if (world[ship->in_room].people) {
sprintf(buf, "$p sails %s.", dirs[dir]);
act(buf, TRUE, world[ship->in_room].people, ship, 0, TO_CHAR | TO_ROOM);
}
obj_to_room(ship, to_room);
if (world[ship->in_room].people) {
sprintf(buf, "$p sails in %s.", from_dir[dir]);
act(buf, TRUE, world[ship->in_room].people, ship, 0, TO_CHAR | TO_ROOM);
}
look_at_room_by_rnum(ch, ship->in_room);
WAIT_STATE(ch, 1 RL_SEC);
}
}
else {
to_room = real_shift(ship->in_room, shift_dir[dir][0], shift_dir[dir][1]);
if (SECT(to_room) != SECT_OCEAN && SECT(to_room) != SECT_RIVER && BUILDING_TYPE(to_room) != BUILDING_DOCKS && (SECT(to_room) != SECT_ROAD || !IS_COMPLETE(to_room) || !world[to_room].type))
msg_to_char(ch, "You can't sail that direction!\r\n");
else if (!IS_COMPLETE(to_room))
msg_to_char(ch, "You can't use an incomplete dock.\r\n");
else if (SECT(to_room) == SECT_BUILDING && dir != world[to_room].building_entrance)
msg_to_char(ch, "You can't enter from this side.\r\n");
else if (SECT(to_room) == SECT_BUILDING && !CAN_USE_ROOM(ch, to_room, 0))
msg_to_char(ch, "You don't have permission to dock.\r\n");
else {
if (world[ship->in_room].people) {
sprintf(buf, "$p sails %s.", dirs[dir]);
act(buf, TRUE, world[ship->in_room].people, ship, 0, TO_CHAR | TO_ROOM);
}
obj_to_room(ship, to_room);
if (world[ship->in_room].people) {
sprintf(buf, "$p sails in %s.", from_dir[dir]);
act(buf, TRUE, world[ship->in_room].people, ship, 0, TO_CHAR | TO_ROOM);
}
look_at_room_by_rnum(ch, ship->in_room);
WAIT_STATE(ch, 1 RL_SEC);
}
}
}
ACMD(do_board) {
struct follow_type *k;
Object ship;
Creature leading = NULL;
room_rnum was_in = ch->in_room;
one_argument(argument, arg);
if (IS_NPC(ch))
return;
else if (!*arg)
msg_to_char(ch, "Board what?\r\n");
else if (!(ship = get_obj_in_list_vis(ch, arg, world[ch->in_room].contents)))
msg_to_char(ch, "You don't see a %s here.\r\n", arg);
else if (GET_OBJ_TYPE(ship) != ITEM_SHIP)
msg_to_char(ch, "You can't board that!\r\n");
else if (!CAN_USE_ROOM(ch, real_room(GET_OBJ_VAL(ship, 2)), 0) && ww_dice(GET_DEXTERITY(ch) + GET_LARCENY(ch), 7) <= 0)
msg_to_char(ch, "You don't have permission to board it.\r\n");
else if (GET_RIDING(ch))
msg_to_char(ch, "You can't board while riding.\r\n");
else if (GET_LEADING(ch) && GET_LEADING(ch)->in_room == ch->in_room && (leading = GET_LEADING(ch)) && BUILDING_TYPE(ch->in_room) != BUILDING_DOCKS)
msg_to_char(ch, "You can't lead an animal on board from here.\r\n");
else if (GET_OBJ_VAL(ship, 1))
msg_to_char(ch, "You can't board the ship until it's finished!\r\n");
else if (real_room(GET_OBJ_VAL(ship, 2)) == NOWHERE)
msg_to_char(ch, "An error occurred in the ship: it has no inside.\r\n");
else {
act("$n boards $p.", TRUE, ch, ship, 0, TO_ROOM);
msg_to_char(ch, "You board it.\r\n");
if (leading)
act("$n is lead on-board.", TRUE, leading, 0, ch, TO_NOTVICT);
char_to_room(ch, real_room(GET_OBJ_VAL(ship, 2)));
look_at_room(ch);
act("$n boards the ship.", TRUE, ch, 0, 0, TO_ROOM);
if (leading) {
char_to_room(leading, real_room(GET_OBJ_VAL(ship, 2)));
act("$n boards the ship.", TRUE, leading, 0, 0, TO_ROOM);
look_at_room(leading);
}
for (k = ch->followers; k; k = 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);
act("$n boards $p.", TRUE, k->follower, ship, 0, TO_ROOM);
char_to_room(k->follower, real_room(GET_OBJ_VAL(ship, 2)));
act("$n boards the ship.", TRUE, k->follower, 0, 0, TO_ROOM);
look_at_room(k->follower);
}
if (BUILDING_TYPE(was_in) != BUILDING_DOCKS)
WAIT_STATE(ch, 2 RL_SEC);
}
}
ACMD(do_disembark) {
Object ship = world[ch->in_room].boat;
Creature leading = NULL;
room_rnum was_in = ch->in_room;
struct follow_type *k;
if (!ship)
msg_to_char(ch, "You can't disembark from here!\r\n");
else if (GET_RIDING(ch))
msg_to_char(ch, "You can't disembark while riding.\r\n");
else if (GET_LEADING(ch) && GET_LEADING(ch)->in_room == ch->in_room && (leading = GET_LEADING(ch)) && BUILDING_TYPE(ship->in_room) != BUILDING_DOCKS)
msg_to_char(ch, "You can't lead an animal off the ship unless it's at a dock.\r\n");
else {
act("$n disembarks from $p.", TRUE, ch, ship, 0, TO_ROOM);
msg_to_char(ch, "You disembark.\r\n");
if (leading)
act("$n is lead off.", TRUE, leading, 0, ch, TO_NOTVICT);
char_to_room(ch, ship->in_room);
act("$n disembarks from $p.", TRUE, ch, ship, 0, TO_ROOM);
look_at_room(ch);
if (leading) {
char_to_room(leading, ship->in_room);
act("$n disembarks from $p.", TRUE, leading, ship, 0, TO_ROOM);
look_at_room(leading);
}
for (k = ch->followers; k; k = 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);
act("$n disembarks from $p.", TRUE, k->follower, ship, 0, TO_ROOM);
char_to_room(k->follower, ship->in_room);
act("$n disembarks from $p.", TRUE, k->follower, ship, 0, TO_ROOM);
look_at_room(k->follower);
}
if (BUILDING_TYPE(ch->in_room) != BUILDING_DOCKS)
WAIT_STATE(ch, 2 RL_SEC);
}
}
struct ship_data_struct {
char *name;
int vnum;
int type;
int science;
int intelligence;
int resources;
int advanced;
} ship_data[] = {
{ "pinnace", os_PINNACE, 0, 1, 3, 60, 0 },
{ "galley", os_GALLEY, 1, 2, 3, 90, 0 },
{ "brigantine", os_BRIGANTINE, 2, 3, 3, 120, 0 },
{ "argosy", os_ARGOSY, 3, 4, 3, 240, 1 },
{ "galleon", os_GALLEON, 4, 5, 3, 480, 1 },
{ "\n", -1, 0, 0, 0, 0 }
};
/*
* Like buildings, ships will take a long time to build. However, they will
* use ONLY logs and iron and will alternate every update between those two.
*/
void process_manufacturing(Creature ch) {
Object ship;
Creature c;
Resource iron[] = { {o_IRON, 1}, END_RESOURCE_LIST };
Resource logs[] = { {o_LOG, 1}, END_RESOURCE_LIST };
for (ship = world[ch->in_room].contents; ship; ship = ship->next_content)
if (GET_OBJ_TYPE(ship) == ITEM_SHIP && GET_OBJ_VAL(ship, 1))
break;
if (!ship) {
msg_to_char(ch, "You try to work on a ship, but there isn't one here!\r\n");
GET_ACTION(ch) = ACT_NONE;
}
else if ((GET_OBJ_VAL(ship, 1) % 2)) {
if (!has_resources(ch, iron, TRUE))
GET_ACTION(ch) = ACT_NONE;
else {
extract_resources(ch, iron, TRUE);
msg_to_char(ch, "You nail the wood onto the structure.\r\n");
act("$n nails the wood onto the structure.", FALSE, ch, 0, 0, TO_ROOM);
GET_OBJ_VAL(ship, 1) -= 1;
}
}
else {
if (!has_resources(ch, logs, TRUE))
GET_ACTION(ch) = ACT_NONE;
else {
extract_resources(ch, logs, TRUE);
msg_to_char(ch, "You position some wood on the structure.\r\n");
act("$n positions the wood on the structure.", FALSE, ch, 0, 0, TO_ROOM);
GET_OBJ_VAL(ship, 1) -= 1;
}
}
if (GET_OBJ_VAL(ship, 1) == 0) {
msg_to_char(ch, "You finish the construction!\r\n");
act("$n finishes the construction!", FALSE, ch, 0, 0, TO_ROOM);
for (c = world[ch->in_room].people; c; c = c->next_in_room)
if (!IS_NPC(c) && GET_ACTION(c) == ACT_MANUFACTURING)
GET_ACTION(c) = ACT_NONE;
}
}
ACMD(do_manufacture) {
Object ship;
int i = 0;
for (ship = world[ch->in_room].contents; ship; ship = ship->next_content)
if (GET_OBJ_TYPE(ship) == ITEM_SHIP && GET_OBJ_VAL(ship, 1))
break;
skip_spaces(&argument);
if (*argument)
for (i = 0; str_cmp(ship_data[i].name, "\n") && (!is_abbrev(argument, ship_data[i].name) || GET_SCIENCE(ch) < ship_data[i].science || GET_INTELLIGENCE(ch) < ship_data[i].intelligence); i++);
if ((BUILDING_TYPE(ch->in_room) != BUILDING_SHIPYARD && BUILDING_TYPE(ch->in_room) != BUILDING_SHIPYARD2) || !IS_COMPLETE(ch->in_room))
msg_to_char(ch, "You can't do that here.\r\n");
else if (GET_ACTION(ch) == ACT_MANUFACTURING) {
msg_to_char(ch, "You stop working on the ship.\r\n");
GET_ACTION(ch) = ACT_NONE;
}
else if (GET_ACTION(ch) != ACT_NONE)
msg_to_char(ch, "You're busy doing something else right now.\r\n");
else if (ship && *argument)
msg_to_char(ch, "A shipyard may only build one ship at a time.\r\n");
else if (!ship && (!*argument || !str_cmp(ship_data[i].name, "\n"))) {
msg_to_char(ch, "What type of ship would you like to build:");
for (i = 0; str_cmp(ship_data[i].name, "\n"); i++)
if (GET_SCIENCE(ch) >= ship_data[i].science && GET_INTELLIGENCE(ch) >= ship_data[i].intelligence)
msg_to_char(ch, " %s", ship_data[i].name);
msg_to_char(ch, "\r\n");
}
else if (ship) {
act("You begin working on $p.", FALSE, ch, ship, 0, TO_CHAR);
act("$n begins working on $p.", FALSE, ch, ship, 0, TO_ROOM);
GET_ACTION(ch) = ACT_MANUFACTURING;
GET_ACTION_TIMER(ch) = 1;
GET_ACTION_ROOM(ch) = ch->in_room;
GET_ACTION_ROTATION(ch) = last_action_rotation;
}
else if (!CAN_USE_ROOM(ch, ch->in_room, 0))
msg_to_char(ch, "You don't have permission to manufacture ships here.\r\n");
else if (ship_data[i].advanced && BUILDING_TYPE(ch->in_room) != BUILDING_SHIPYARD2)
msg_to_char(ch, "You can't build that without an advanced shipyard.\r\n");
else {
ship = create_ship(ship_data[i].vnum, get_id_by_empire(ch), ch->in_room);
msg_to_char(ch, "You begin working on a %s.\r\n", ship_data[i].name);
act("$n begins to build a ship.", FALSE, ch, 0, 0, TO_ROOM);
GET_ACTION(ch) = ACT_MANUFACTURING;
GET_ACTION_TIMER(ch) = 1;
GET_ACTION_ROOM(ch) = ch->in_room;
GET_ACTION_ROTATION(ch) = last_action_rotation;
GET_OBJ_VAL(ship, 1) = ship_data[i].resources;
}
}
/* Returns TRUE if it loads the object */
bool load_one_obj_to_boat(Creature ch, Object obj, room_rnum to_room, Object ship) {
if (ROOM_WEIGHT(to_room) + GET_OBJ_WEIGHT(obj) < room_capacity[(int) world[to_room].type]) {
obj_to_room(obj, to_room);
act("You load $p into $P.", FALSE, ch, obj, ship, TO_CHAR);
return TRUE;
}
return FALSE;
}
/* Returns 1 if totally done, 0 if the room fills, and -1 if nothing could be loaded */
int load_all_objs_to_boat(Creature ch, room_rnum from, room_rnum to, Object ship) {
Object o, next_o;
bool done = TRUE, any = FALSE;
for (o = world[from].contents; o; o = next_o) {
next_o = o->next_content;
/* We can never load a ship */
if (GET_OBJ_TYPE(o) == ITEM_SHIP)
continue;
/* We can only load a !take item onto a Galleon (catapult, etc) */
if (!CAN_WEAR(o, ITEM_WEAR_TAKE) && GET_OBJ_VAL(ship, 0) != SHIP_GALLEON)
continue;
if (ROOM_WEIGHT(to) + GET_OBJ_WEIGHT(o) < room_capacity[(int) world[to].type]) {
obj_to_room(o, to);
any = TRUE;
}
else
done = FALSE;
}
/*
* done will still be TRUE if we never failed to load an item
* any will be TRUE if any item was loaded
* if not, this puppy is full!
*/
if (done)
return 1;
else if (any)
return 0;
else
return -1;
}
ACMD(do_load_boat) {
Object ship, to_load = NULL;
room_rnum i;
int val;
bool done = FALSE;
two_arguments(argument, arg, buf);
if (BUILDING_TYPE(ch->in_room) != BUILDING_DOCKS)
msg_to_char(ch, "You can only load a ship at the dock.\r\n");
else if (!IS_COMPLETE(ch->in_room))
msg_to_char(ch, "The docks are incomplete.\r\n");
else if (!*arg)
msg_to_char(ch, "What ship would you like to load?\r\n");
else if (!(ship = get_obj_in_list_vis(ch, arg, world[ch->in_room].contents)))
msg_to_char(ch, "There's no ship by that name here.\r\n");
else if (GET_OBJ_TYPE(ship) != ITEM_SHIP)
msg_to_char(ch, "That's not a ship!\r\n");
else if (*buf && !(to_load = get_obj_in_list_vis(ch, buf, ch->carrying)) && !(to_load = get_obj_in_list_vis(ch, buf, world[ch->in_room].contents)))
msg_to_char(ch, "You don't seem to have a %s to load.\r\n", buf);
else if (to_load && GET_OBJ_TYPE(to_load) == ITEM_SHIP)
msg_to_char(ch, "You can't load a ship onto a ship!\r\n");
else if (to_load && !CAN_WEAR(to_load, ITEM_WEAR_TAKE) && GET_OBJ_VAL(ship, 0) != SHIP_GALLEON)
msg_to_char(ch, "You can't load that onto this ship!\r\n");
else {
for (i = MAP_SIZE; i <= top_of_world && !done; i++) {
if (HOME_ROOM(i) != real_room(GET_OBJ_VAL(ship, 2)))
continue;
if (ROOM_TYPE(i) != RTYPE_B_STORAGE && ROOM_TYPE(i) != RTYPE_B_ONDECK)
continue;
if (to_load) {
if (load_one_obj_to_boat(ch, to_load, i, ship))
return;
}
else {
if ((val = load_all_objs_to_boat(ch, ch->in_room, i, ship)) == 1)
done = TRUE;
if (val != -1) {
act("You load some cargo into $p.", FALSE, ch, ship, 0, TO_CHAR);
act("$n loads some cargo into $p.", FALSE, ch, ship, 0, TO_ROOM);
}
/* else nothing was loaded at all to this room */
}
}
if (!to_load && !done)
act("$p is full.", FALSE, ch, ship, 0, TO_CHAR);
}
}
/*
* Returns:
* -2: nothing could be unloaded, docks are full
* -1: some stuff was unloaded, but docks were full
* 0: room was empty
* 1: room finished
*/
int perform_unload_boat(Creature ch, room_rnum from, room_rnum to, Object ship) {
Object o, next_o;
bool done = TRUE, any = FALSE;
for (o = world[from].contents; o; o = next_o) {
next_o = o->next_content;
/* We can never load a ship */
if (GET_OBJ_TYPE(o) == ITEM_SHIP || GET_OBJ_TYPE(o) == ITEM_HELM || GET_OBJ_TYPE(o) == ITEM_WINDOW)
continue;
/* It's not necessary to check for ITEM_WEAR_TAKE.. if it got here we'll take it out */
if (ROOM_WEIGHT(to) + GET_OBJ_WEIGHT(o) < building_capacity[(int) world[to].type]) {
obj_to_room(o, to);
any = TRUE;
}
else
done = FALSE;
}
if (!done && !any)
return -2;
else if (!done && any)
return -1;
else if (done && !any)
return 0;
else
return 1;
}
ACMD(do_unload_boat) {
Object ship;
room_rnum i;
int val;
bool more = FALSE;
one_argument(argument, arg);
if (BUILDING_TYPE(ch->in_room) != BUILDING_DOCKS)
msg_to_char(ch, "You can only unload a ship at the dock.\r\n");
else if (!IS_COMPLETE(ch->in_room))
msg_to_char(ch, "The docks are incomplete.\r\n");
else if (!*arg)
msg_to_char(ch, "What ship would you like to load?\r\n");
else if (!(ship = get_obj_in_list_vis(ch, arg, world[ch->in_room].contents)))
msg_to_char(ch, "There's no ship by that name here.\r\n");
else if (GET_OBJ_TYPE(ship) != ITEM_SHIP)
msg_to_char(ch, "That's not a ship!\r\n");
else {
for (i = MAP_SIZE; i <= top_of_world; i++) {
if (HOME_ROOM(i) != real_room(GET_OBJ_VAL(ship, 2)))
continue;
if (ROOM_TYPE(i) != RTYPE_B_STORAGE && ROOM_TYPE(i) != RTYPE_B_ONDECK)
continue;
if ((val = perform_unload_boat(ch, i, ch->in_room, ship)) < 0)
more = TRUE;
if (val != 0 && val != -2) {
act("You unload some cargo from $p.", FALSE, ch, ship, 0, TO_CHAR);
act("$n unloads some cargo from $p.", FALSE, ch, ship, 0, TO_ROOM);
}
}
if (more)
msg_to_char(ch, "You can't unload anything else, the docks are full!\r\n");
}
}