/* ************************************************************************ * 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"); } }