/** Unlock a lock (user interface). * \verbatim * This implements @unlock. * \endverbatim * \param player the enactor. * \param name name of object to unlock. * \param type type of lock to unlock. */ void do_unlock(dbref player, const char *name, lock_type type) { dbref thing; char *sp; lock_type real_type; /* check for '@unlock <object>/<atr>' */ sp = strchr(name, '/'); if (sp) { notify(player, "Use @atrlock."); return; } if ((thing = match_controlled(player, name)) != NOTHING) { if ((real_type = check_lock_type(player, thing, type)) != NULL) { if (getlock(thing, real_type) == TRUE_BOOLEXP) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s (already) unlocked."), Name(thing), unparse_dbref(thing), real_type); } else if (delete_lock(player, thing, real_type)) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s unlocked."), Name(thing), unparse_dbref(thing), real_type); if (!IsPlayer(thing)) { char lmbuf[1024]; ModTime(thing) = mudtime; snprintf(lmbuf, 1023, "%s lock[#%d]", real_type, player); lmbuf[strlen(lmbuf)+1] = '\0'; set_lmod(thing, lmbuf); } } else notify(player, T("Permission denied.")); } } }
/** Debit a player's pennies, if they can afford it. * \param who player to debit. * \param cost number of pennies to debit. * \retval 1 player successfully debited. * \retval 0 player can't afford the cost. */ int payfor(dbref who, int cost) { /* subtract cost from who's pennies */ int tmp; dbref owner; if ((cost == 0) || NoPay(who)) return 1; owner = Owner(who); if ((tmp = Pennies(owner)) >= cost) { if (Track_Money(owner)) { notify_format(owner, T("GAME: %s(%s) spent %d %s."), AName(who, AN_SYS, NULL), unparse_dbref(who), cost, (cost == 1) ? MONEY : MONIES); } s_Pennies(owner, tmp - cost); return 1; } else { if (Track_Money(owner)) { notify_format(owner, T("GAME: %s(%s) tried to spend %d %s."), AName(who, AN_SYS, NULL), unparse_dbref(who), cost, (cost == 1) ? MONEY : MONIES); } return 0; } }
/** Unlock a lock (user interface). * \verbatim * This implements @unlock. * \endverbatim * \param player the enactor. * \param name name of object to unlock. * \param type type of lock to unlock. */ void do_unlock(dbref player, const char *name, lock_type type) { dbref thing; lock_type real_type; /* check for '@unlock <object>/<atr>' */ if (strchr(name, '/')) { do_atrlock(player, name, "off"); return; } if ((thing = match_controlled(player, name)) != NOTHING) { if ((real_type = check_lock_type(player, thing, type)) != NULL) { if (getlock(thing, real_type) == TRUE_BOOLEXP) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s (already) unlocked."), AName(thing, AN_SYS, NULL), unparse_dbref(thing), real_type); } else if (delete_lock(player, thing, real_type)) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s unlocked."), AName(thing, AN_SYS, NULL), unparse_dbref(thing), real_type); if (!IsPlayer(thing)) ModTime(thing) = mudtime; } else notify(player, T("Permission denied.")); } } }
/** Display information on an attribute from the table. * \verbatim * Top-level function for @attribute. * \endverbatim * \param player the enactor. * \param name the name of the attribute. */ void do_attribute_info(dbref player, char *name) { ATTR *ap; if (!name || !*name) { notify(player, T("Which attribute do you mean?")); return; } /* Is this attribute in the table? */ if (*name == '@') name++; ap = aname_hash_lookup(name); if (!ap) { notify(player, T("That attribute isn't in the attribute table")); return; } notify_format(player, "%9s: %s", T("Attribute"), AL_NAME(ap)); if (ap->flags & AF_RLIMIT) { notify_format(player, "%9s: %s", T("Limit"), display_attr_limit(ap)); } else if (ap->flags & AF_ENUM) { notify_format(player, "%9s: %s", T("Enum"), display_attr_limit(ap)); } notify_format(player, "%9s: %s", T("Flags"), privs_to_string(attr_privs_view, AL_FLAGS(ap))); notify_format(player, "%9s: %s", T("Creator"), unparse_dbref(AL_CREATOR(ap))); return; }
/** Open a new exit. * \verbatim * This is the top-level function for @open. It calls do_real_open() * to do the real work of opening both the exit forward and the exit back. * \endverbatim * \param player the enactor. * \param direction name of the exit forward. * \param links 1-based array, possibly containing name of destination, name of exit back, * and room to open initial exit from. */ void do_open(dbref player, const char *direction, char **links) { dbref forward; dbref source = NOTHING; if (links[3]) { source = match_result(player, links[3], TYPE_ROOM, MAT_HERE | MAT_ABSOLUTE | MAT_TYPE); if (!GoodObject(source)) { notify(player, T("Open from where?")); return; } } forward = do_real_open(player, direction, links[1], source); if (links[2] && GoodObject(forward) && GoodObject(Location(forward))) { char sourcestr[SBUF_LEN]; /* SBUF_LEN is the size used by unparse_dbref */ if (!GoodObject(source)) { if (IsRoom(player)) { source = player; } else if (IsExit(player)) { source = Home(player); } else { source = Location(player); } } strcpy(sourcestr, unparse_dbref(source)); do_real_open(player, links[2], sourcestr, Location(forward)); } }
/** Set/lock a lock (user interface). * \verbatim * This implements @lock. * \endverbatim * \param player the enactor. * \param name name of object to lock. * \param keyname key to lock the lock to, as a string. * \param type type of lock to lock. */ void do_lock(dbref player, const char *name, const char *keyname, lock_type type) { lock_type real_type; dbref thing; boolexp key; /* check for '@lock <object>/<atr>' */ if (strchr(name, '/')) { do_atrlock(player, name, "on"); return; } if (!keyname || !*keyname) { do_unlock(player, name, type); return; } switch (thing = match_result(player, name, NOTYPE, MAT_EVERYTHING)) { case NOTHING: notify(player, T("I don't see what you want to lock!")); return; case AMBIGUOUS: notify(player, T("I don't know which one you want to lock!")); return; default: if (!controls(player, thing)) { notify(player, T("You can't lock that!")); return; } if (IsGarbage(thing)) { notify(player, T("Why would you want to lock garbage?")); return; } break; } key = parse_boolexp(player, keyname, type); /* do the lock */ if (key == TRUE_BOOLEXP) { notify(player, T("I don't understand that key.")); } else { if ((real_type = check_lock_type(player, thing, type)) != NULL) { /* everything ok, do it */ if (add_lock(player, thing, real_type, key, LF_DEFAULT)) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s locked."), AName(thing, AN_SYS, NULL), unparse_dbref(thing), real_type); if (!IsPlayer(thing)) ModTime(thing) = mudtime; } else { notify(player, T("Permission denied.")); /* Done by a failed add_lock() // free_boolexp(key); */ } } else free_boolexp(key); } }
/** A wrapper for real_did_it that can set %0 and %1 to dbrefs. * \param player the enactor. * \param thing object being triggered. * \param what message attribute for enactor. * \param def default message to enactor. * \param owhat message attribute for others. * \param odef default message to others. * \param awhat action attribute to trigger. * \param loc location in which action is taking place. * \param env0 dbref to pass as %0, or NOTHING. * \param env1 dbref to pass as %1, or NOTHING. * \param flags interaction flags to pass to real_did_it. * \retval 0 no attributes were present, only defaults were used if given. * \retval 1 some attributes were evaluated and used. */ int did_it_with(dbref player, dbref thing, const char *what, const char *def, const char *owhat, const char *odef, const char *awhat, dbref loc, dbref env0, dbref env1, int flags, int an_flags) { PE_REGS *pe_regs = pe_regs_create(PE_REGS_ARG, "did_it_with"); int retval; if (env0 != NOTHING) { pe_regs_setenv(pe_regs, 0, unparse_dbref(env0)); } if (env1 != NOTHING) { pe_regs_setenv(pe_regs, 1, unparse_dbref(env1)); } retval = real_did_it(player, thing, what, def, owhat, odef, awhat, loc, pe_regs, flags, an_flags); pe_regs_free(pe_regs); return retval; }
/* board a ship through the ship object */ void board_ship(dbref player, char *which, char *code) { ATTR *a; char *bcode; dbref obj, nav, bay; int security; /* find the shipobj */ obj = match_result(player, which, TYPE_THING, MAT_NEAR_THINGS); if (!IsShipObj(obj)) { notify(player, "Can't find that ship."); return; } /* see if it's got an HSNAV */ nav = atr_parse_dbref(obj, "HSNAV"); if (!IsShip(nav)) { notify(player, "That is not a valid ship object."); return; } /* check the boarding code, if necessary */ security = atr_parse_integer(nav, "SECURITY", 0); if (security) { a = atr_get(nav, "BOARDING_CODE"); if (a) { bcode = atr_value(a); if (strcmp(bcode, code)) { notify(player, "Invalid boarding code."); return; } } } /* check for a BAY on the nav, otherwise go to the nav's location */ bay = atr_parse_dbref(nav, "BAY"); if (!RealGoodObject(bay)) { bay = Location(nav); } atr_add(player, "HSPACE", unparse_dbref(nav), hs_options.space_wiz, 0); notify_except(obj, Location(player), player, tprintf("%s boards the %s.", Name(player), Name(obj)), 0); notify_except(obj, bay, player, tprintf("%s boards through the main hatch.", Name(player)), 0); moveto(player, bay, hs_options.space_wiz, NULL); }
static void display_attr_info(dbref player, ATTR *ap) { notify_format(player, "%9s: %s", T("Attribute"), AL_NAME(ap)); if (ap->flags & AF_RLIMIT) { notify_format(player, "%9s: %s", T("Limit"), display_attr_limit(ap)); } else if (ap->flags & AF_ENUM) { notify_format(player, "%9s: %s", T("Enum"), display_attr_limit(ap)); } notify_format(player, "%9s: %s", T("Flags"), privs_to_string(attr_privs_view, AL_FLAGS(ap))); notify_format(player, "%9s: %s", T("Creator"), unparse_dbref(AL_CREATOR(ap))); return; }
/** Display the access list. * \param player enactor. * Sends the complete access list to the player. */ void do_list_access(dbref player) { struct access *ap; acsflag *c; char flaglist[BUFFER_LEN]; int rulenum = 0; char *bp; for (ap = access_top; ap; ap = ap->next) { rulenum++; if (ap->can != ACS_SITELOCK) { bp = flaglist; for (c = acslist; c->name; c++) { if (c->flag == ACS_DEFAULT) continue; if (ap->can & c->flag) { safe_chr(' ', flaglist, &bp); safe_str(c->name, flaglist, &bp); } if (c->toggle && (ap->cant & c->flag)) { safe_chr(' ', flaglist, &bp); safe_chr('!', flaglist, &bp); safe_str(c->name, flaglist, &bp); } } *bp = '\0'; notify_format(player, T("%3d SITE: %-20s DBREF: %-6s FLAGS:%s"), rulenum, ap->host, unparse_dbref(ap->who), flaglist); notify_format(player, T(" COMMENT: %s"), ap->comment ? ap->comment : ""); } else { notify(player, T ("---- @sitelock will add sites immediately below this line ----")); } } if (rulenum == 0) { notify(player, T("There are no access rules.")); } }
/** Open a new exit. * \verbatim * This is the top-level function for @open. It calls do_real_open() * to do the real work of opening both the exit forward and the exit back. * \endverbatim * \param player the enactor. * \param direction name of the exit forward. * \param links 1-based array, possibly containing name of destination, name of exit back, * and room to open initial exit from. * \param pe_info the pe_info to use for any lock checks */ void do_open(dbref player, const char *direction, char **links, NEW_PE_INFO *pe_info) { dbref forward; dbref source = NOTHING; if (links[3]) { source = match_result(player, links[3], TYPE_ROOM, MAT_HERE | MAT_ABSOLUTE | MAT_TYPE); if (!GoodObject(source)) { notify(player, T("Open from where?")); return; } } if (links[5]) { if (!make_first_free_wrapper(player, links[5])) return; } if (links[4]) { if (!make_first_free_wrapper(player, links[4])) return; } forward = do_real_open(player, direction, links[1], source, pe_info); if (links[2] && *links[2] && GoodObject(forward) && GoodObject(Location(forward))) { char sourcestr[SBUF_LEN]; /* SBUF_LEN is the size used by unparse_dbref */ if (!GoodObject(source)) { source = speech_loc(player); } strcpy(sourcestr, unparse_dbref(source)); do_real_open(player, links[2], sourcestr, Location(forward), pe_info); } }
/** Create an exit. * This function opens an exit and optionally links it. * \param player the enactor. * \param direction the name of the exit. * \param linkto the room to link to, as a string. * \param pseudo a phony location for player if a back exit is needed. This is bpass by do_open() as the source room of the back exit. * \return dbref of the new exit, or NOTHING. */ dbref do_real_open(dbref player, const char *direction, const char *linkto, dbref pseudo) { dbref loc = (pseudo != NOTHING) ? pseudo : (IsExit(player) ? Source(player) : (IsRoom(player) ? player : Location(player))); dbref new_exit; char *flaglist, *flagname; char flagbuff[BUFFER_LEN]; char *name = NULL; char *alias = NULL; if (!command_check_byname(player, "@dig")) { notify(player, T("Permission denied.")); return NOTHING; } if ((loc == NOTHING) || (!IsRoom(loc))) { notify(player, T("Sorry, you can only make exits out of rooms.")); return NOTHING; } if (Going(loc)) { notify(player, T("You can't make an exit in a place that's crumbling.")); return NOTHING; } if (!*direction) { notify(player, T("Open where?")); return NOTHING; } else if (ok_object_name ((char *) direction, player, NOTHING, TYPE_EXIT, &name, &alias) < 1) { notify(player, T("That's a strange name for an exit!")); if (name) mush_free(name, "name.newname"); if (alias) mush_free(alias, "name.newname"); return NOTHING; } if (!Open_Anywhere(player) && !controls(player, loc)) { notify(player, T("Permission denied.")); } else if (can_pay_fees(player, EXIT_COST)) { /* create the exit */ new_exit = new_object(); /* initialize everything */ set_name(new_exit, name); if (alias && *alias != ALIAS_DELIMITER) atr_add(new_exit, "ALIAS", alias, player, 0); Owner(new_exit) = Owner(player); Zone(new_exit) = Zone(player); Source(new_exit) = loc; Type(new_exit) = TYPE_EXIT; Flags(new_exit) = new_flag_bitmask("FLAG"); strcpy(flagbuff, options.exit_flags); flaglist = trim_space_sep(flagbuff, ' '); if (*flaglist != '\0') { while (flaglist) { flagname = split_token(&flaglist, ' '); twiddle_flag_internal("FLAG", new_exit, flagname, 0); } } mush_free(name, "name.newname"); if (alias) mush_free(alias, "name.newname"); /* link it in */ PUSH(new_exit, Exits(loc)); /* and we're done */ notify_format(player, T("Opened exit %s"), unparse_dbref(new_exit)); /* check second arg to see if we should do a link */ if (linkto && *linkto != '\0') { notify(player, T("Trying to link...")); if ((loc = check_var_link(linkto)) == NOTHING) loc = parse_linkable_room(player, linkto); if (loc != NOTHING) { if (!payfor(player, LINK_COST)) { notify_format(player, T("You don't have enough %s to link."), MONIES); } else { /* it's ok, link it */ Location(new_exit) = loc; notify_format(player, T("Linked exit #%d to #%d"), new_exit, loc); } } } current_state.exits++; local_data_create(new_exit); queue_event(player, "OBJECT`CREATE", "%s", unparse_objid(new_exit)); return new_exit; } if (name) mush_free(name, "name.newname"); if (alias) mush_free(alias, "name.newname"); return NOTHING; }
/** Clone an object. * \verbatim * This is the top-level function for @clone, which creates a duplicate * of a (non-player) object. * \endverbatim * \param player the enactor. * \param name the name of the object to clone. * \param newname the name to give the duplicate. * \param preserve if 1, preserve ownership and privileges on duplicate. * \paran newdbref the (unparsed) dbref to give the object, or NULL to use the next free * \return dbref of the duplicate, or NOTHING. */ dbref do_clone(dbref player, char *name, char *newname, int preserve, char *newdbref) { dbref clone, thing; char dbnum[BUFFER_LEN]; thing = noisy_match_result(player, name, NOTYPE, MAT_EVERYTHING); if ((thing == NOTHING)) return NOTHING; if (newname && *newname && !ok_name(newname, IsExit(thing))) { notify(player, T("That is not a reasonable name.")); return NOTHING; } if (!controls(player, thing) || IsPlayer(thing) || (IsRoom(thing) && !command_check_byname(player, "@dig")) || (IsExit(thing) && !command_check_byname(player, "@open")) || (IsThing(thing) && !command_check_byname(player, "@create"))) { notify(player, T("Permission denied.")); return NOTHING; } /* don't allow cloning of destructed things */ if (IsGarbage(thing)) { notify(player, T("There's nothing left of it to clone!")); return NOTHING; } if (preserve && !Wizard(player)) { notify(player, T("You cannot @CLONE/PRESERVE. Use normal @CLONE instead.")); return NOTHING; } if (!make_first_free_wrapper(player, newdbref)) { return NOTHING; } /* make sure owner can afford it */ switch (Typeof(thing)) { case TYPE_THING: if (can_pay_fees(player, Pennies(thing))) { clone = clone_object(player, thing, newname, preserve); notify_format(player, T("Cloned: Object %s."), unparse_dbref(clone)); if (IsRoom(player)) moveto(clone, player, player, "cloned"); else moveto(clone, Location(player), player, "cloned"); current_state.things++; local_data_clone(clone, thing); real_did_it(player, clone, NULL, NULL, NULL, NULL, "ACLONE", NOTHING, global_eval_context.wenv, 0); return clone; } return NOTHING; break; case TYPE_ROOM: if (can_pay_fees(player, ROOM_COST)) { clone = clone_object(player, thing, newname, preserve); Exits(clone) = NOTHING; notify_format(player, T("Cloned: Room #%d."), clone); current_state.rooms++; local_data_clone(clone, thing); real_did_it(player, clone, NULL, NULL, NULL, NULL, "ACLONE", NOTHING, global_eval_context.wenv, 0); return clone; } return NOTHING; break; case TYPE_EXIT: /* For exits, we don't want people to be able to link it to a location they can't with @open. So, all this stuff. */ switch (Location(thing)) { case NOTHING: strcpy(dbnum, "#-1"); break; case HOME: strcpy(dbnum, "home"); break; case AMBIGUOUS: strcpy(dbnum, "variable"); break; default: strcpy(dbnum, unparse_dbref(Location(thing))); } if (newname && *newname) clone = do_real_open(player, newname, dbnum, NOTHING); else clone = do_real_open(player, Name(thing), dbnum, NOTHING); if (!GoodObject(clone)) { return NOTHING; } else { atr_cpy(clone, thing); clone_locks(player, thing, clone); Zone(clone) = Zone(thing); Parent(clone) = Parent(thing); Flags(clone) = clone_flag_bitmask("FLAG", Flags(thing)); if (!preserve) { clear_flag_internal(clone, "WIZARD"); clear_flag_internal(clone, "ROYALTY"); Warnings(clone) = 0; /* zap warnings */ Powers(clone) = new_flag_bitmask("POWER"); /* zap powers */ } else { Warnings(clone) = Warnings(thing); Powers(clone) = clone_flag_bitmask("POWER", Powers(thing)); } if (Wizard(clone) || Royalty(clone) || Warnings(clone) || !null_flagmask("POWER", Powers(clone))) notify(player, T ("Warning: @CLONE/PRESERVE on an object with WIZ, ROY, @powers, or @warnings.")); notify_format(player, T("Cloned: Exit #%d."), clone); local_data_clone(clone, thing); return clone; } } return NOTHING; }
/** Create a thing. * \verbatim * This is the top-level function for @create. * \endverbatim * \param player the enactor. * \param name name of thing to create. * \param cost pennies spent in creation. * \paran newdbref the (unparsed) dbref to give the object, or NULL to use the next free * \return dbref of new thing, or NOTHING. */ dbref do_create(dbref player, char *name, int cost, char *newdbref) { dbref loc; dbref thing; char *flaglist, *flagname; char flagbuff[BUFFER_LEN]; if (*name == '\0') { notify(player, T("Create what?")); return NOTHING; } else if (!ok_name(name, 0)) { notify(player, T("That's a silly name for a thing!")); return NOTHING; } else if (cost < OBJECT_COST) { cost = OBJECT_COST; } if (!make_first_free_wrapper(player, newdbref)) { return NOTHING; } if (can_pay_fees(player, cost)) { /* create the object */ thing = new_object(); /* initialize everything */ set_name(thing, name); if (!IsExit(player)) /* Exits shouldn't have contents! */ Location(thing) = player; else Location(thing) = Source(player); Owner(thing) = Owner(player); Zone(thing) = Zone(player); s_Pennies(thing, cost); Type(thing) = TYPE_THING; Flags(thing) = new_flag_bitmask("FLAG"); strcpy(flagbuff, options.thing_flags); flaglist = trim_space_sep(flagbuff, ' '); if (*flaglist != '\0') { while (flaglist) { flagname = split_token(&flaglist, ' '); twiddle_flag_internal("FLAG", thing, flagname, 0); } } /* home is here (if we can link to it) or player's home */ if ((loc = Location(player)) != NOTHING && (controls(player, loc) || Abode(loc))) { Home(thing) = loc; /* home */ } else { Home(thing) = Home(player); /* home */ } /* link it in */ if (!IsExit(player)) PUSH(thing, Contents(player)); else PUSH(thing, Contents(Source(player))); /* and we're done */ notify_format(player, T("Created: Object %s."), unparse_dbref(thing)); current_state.things++; local_data_create(thing); queue_event(player, "OBJECT`CREATE", "%s", unparse_objid(thing)); return thing; } return NOTHING; }
/** Set/lock a lock (user interface). * \verbatim * This implements @lock. * \endverbatim * \param player the enactor. * \param name name of object to lock. * \param keyname key to lock the lock to, as a string. * \param type type of lock to lock. */ void do_lock(dbref player, const char *name, const char *keyname, lock_type type) { lock_type real_type; dbref thing; boolexp key; char *sp; /* check for '@lock <object>/<atr>' */ sp = strchr(name, '/'); if (sp) { do_atrlock(player, name, keyname, 0); return; } if (!keyname || !*keyname) { do_unlock(player, name, type); return; } switch (thing = match_result(player, name, NOTYPE, MAT_EVERYTHING)) { case NOTHING: notify(player, T("I don't see what you want to lock!")); return; case AMBIGUOUS: notify(player, T("I don't know which one you want to lock!")); return; default: if (!controls(player, thing)) { notify(player, T("You can't lock that!")); return; } if (IsGarbage(thing)) { notify(player, T("Why would you want to lock garbage?")); return; } break; } key = parse_boolexp(player, keyname, type); /* do the lock */ if (key == TRUE_BOOLEXP) { notify(player, T("I don't understand that key.")); } else { if ((real_type = check_lock_type(player, thing, type)) != NULL) { /* everything ok, do it */ if (add_lock(player, thing, real_type, key, -1)) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s locked."), Name(thing), unparse_dbref(thing), real_type); if (!IsPlayer(thing)) { char lmbuf[1024]; ModTime(thing) = mudtime; snprintf(lmbuf, 1023, "%s lock[#%d]", real_type, player); lmbuf[strlen(lmbuf)+1] = '\0'; set_lmod(thing, lmbuf); } } else { notify(player, T("Permission denied.")); free_boolexp(key); } } else free_boolexp(key); } }
/* leave a flying ship through the escape pod */ void emergency_eject(dbref player) { dbref nav, pad; hship *ship; hcelestial *cel, *min_cel; ATTR *a; char *r, *s; char buff[512]; double dist, min_dist; dbref min_pad; hship *sptr, *min_ship; /* check for a BAY */ a = atr_get(Location(player), "BAY"); if (!a) { /* no BAY, see if we're next to the nav console */ ship = find_ship(player); if (ship) { if (Location(ship->objnum) != Location(player)) { notify(player, "You can't eject from here."); return; } } } else { /* there's a BAY, see if the ship is valid */ nav = parse_dbref(atr_value(a)); if (!IsShip(nav)) { notify(player, "You can't eject from here."); return; } ship = find_ship_by_nav(nav); } if (!ship) { notify(player, "You can't eject from here."); return; } /* only eject when flying, not when landing or docking */ if (!ship->uid || ship->landed || ship->docked) { notify(player, "You may only eject while flying."); return; } /* find a planet with a drop pad */ min_pad = NOTHING; min_dist = 1000000.0; min_cel = NULL; for (cel = ship->uid->head_celestial; cel; cel = cel->next) { if (!HasFlag(cel->type, HS_PLANET)) continue; pad = atr_parse_dbref(cel->objnum, "DROPPADS"); if (!RealGoodObject(pad)) continue; dist = ship_celestial_distance(ship, cel); if (dist < min_dist) { min_dist = dist; min_pad = pad; min_cel = cel; } } min_ship = NULL; for (sptr = ship->uid->head_ship; sptr; sptr = sptr->next) { if (min_cel) break; if (!HasFlag(sptr->type, HS_STATION | HS_CAPITAL)) continue; pad = atr_parse_dbref(sptr->objnum, "BAY"); if (!RealGoodObject(pad)) continue; dist = ship_distance(ship, sptr); if (dist < min_dist) { min_cel = NULL; min_ship = sptr; min_dist = dist; min_pad = pad; } } if (!RealGoodObject(min_pad)) { notify(player, "There is nowhere to eject to!"); return; } /* finish up by setting HSPACE and notifying everybody of the move */ if (min_ship) { atr_add(player, "HSPACE", unparse_dbref(min_ship->objnum), hs_options.space_wiz, 0); } else if (min_cel) { atr_add(player, "HSPACE", unparse_dbref(min_cel->objnum), hs_options.space_wiz, 0); } else { SPACEWALL("Weird problem in eject."); notify(player, "Bad space object. Contact an administrator."); return; } notify_except(Location(player), Location(player), player, tprintf("%s ejects in an emergency escape pod!", Name(player)), 0); notify_except(min_pad, min_pad, player, tprintf("%s crash lands in an emergency escape pod!", Name(player)), 0); if (min_ship) { notify_consoles(min_ship, tprintf("%s%s-%s Emergency ejection pod automatically tractored into the docking back.", ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL)); } moveto(player, min_pad, hs_options.space_wiz, NULL); }
/* leave a landed/docked ship through the hatch */ void disembark(dbref player) { dbref nav, obj, newobj; hship *ship; ATTR *a; int security; /* check if we can disembark from here */ a = atr_get(Location(player), "BAY"); if (!a) { /* no BAY, check if we're near the nav console */ ship = find_ship(player); if (ship) { if (Location(ship->objnum) != Location(player)) { notify(player, "You can't disembark from here."); return; } } } else { /* there's a BAY here, make sure it's a good one */ nav = parse_dbref(atr_value(a)); if (!IsShip(nav)) { notify(player, "You can't disembark from here."); return; } ship = find_ship_by_nav(nav); } if (!ship) { notify(player, "You can't disembark from here."); return; } /* no ditching in space, or early after launching, or prematurely when landing */ if ((ship->uid || ship->landing || ship->launching) && !ship->linked) { notify(player, "You can't disembark while in space."); return; } obj = atr_parse_dbref(ship->objnum, "SHIPOBJ"); if (!RealGoodObject(obj)) { notify(player, "This ship can not be disembarked."); return; } /* check whether we're docking or landing, save the new space object */ if (ship->landed) { newobj = ship->landed->objnum; } else if (ship->docked) { newobj = ship->docked->objnum; } else if (ship->linked) { newobj = ship->linked->objnum; } else { notify(player, "You can't disembark while in space."); return; } if (ship->linked) { /* check the boarding code, if necessary */ security = atr_parse_integer(ship->linked->objnum, "SECURITY", 0); if (security) { notify(player, "Unable to use boarding link while the other ship has security enabled."); return; } security = atr_parse_integer(ship->objnum, "SECURITY", 0); if (security) { notify(player, "Unable to use boarding link while security is enabled."); return; } obj = atr_parse_dbref(ship->linked->objnum, "BAY"); if (!RealGoodObject(obj)) obj = Location(ship->linked->objnum); moveto(player, obj, hs_options.space_wiz, NULL); } else { moveto(player, Location(obj), hs_options.space_wiz, NULL); } /* finish up by setting HSPACE attribute and notifying everybody about the move */ atr_add(player, "HSPACE", unparse_dbref(newobj), hs_options.space_wiz, 0); notify_except(obj, Location(player), player, tprintf("%s disembarks through the main hatch.", Name(player)), 0); notify_except(obj, Location(obj), player, tprintf("%s disembarks from the %s.", Name(player), Name(obj)), 0); return; }
/* man console command */ void man_console(dbref player, char *where) { hship *ship; hconsole *con; dbref console; dbref manner, manning; hweapon *pri, *sec; char *prompt; int ptype, stype, type; if (Typeof(player) != TYPE_PLAYER && hs_options.forbid_puppets) { notify(player, "Only players may man this console."); return; } console = match_result(player, where, TYPE_THING, MAT_NEAR_THINGS); switch (console) { case NOTHING: notify(player, "I don't see that here."); return; case AMBIGUOUS: notify(player, "I don't know which you mean!"); return; } /* don't need to do this now because we want to allow you to reman consoles easily for equipment changes */ /*manner = get_user(console); if (manner == player) { notify(player, "You are already manning that console."); return; }*/ if (!IsConsole(console) && !IsShip(console)) { notify(player, "You cannot man that."); return; } if (IsConsole(console)) { con = find_console(console); if (!con) { notify(player, "That console has not been activated."); return; } pri = &(con->primary); sec = &(con->secondary); prompt = &(con->prompt); ship = find_ship(console); } else if (IsShip(console)) { con = NULL; ship = find_ship_by_nav(console); if (ship) { pri = &(ship->primary); sec = &(ship->secondary); prompt = &(ship->prompt); } } else{ ship = NULL; } if (!ship) { notify(player, "Invalid ship object. Please contact your flight mechanic immediately!"); return; } if (InCombat(ship)) { notify(player, "Can't reload weapons in combat!"); stype = sec->type; ptype = pri->type; } else { ptype = load_weapon(player, pri, HS_PRIMARY); stype = load_weapon(player, sec, HS_SECONDARY); } type = HasFlag(ptype | stype, HS_ANY_WEAPON); if (con) { /* this is an auxiliary console */ /* no missiles on the aux consoles */ if (HasFlag(type, HS_MISSILE)) { clear_weapon(pri); clear_weapon(sec); notify(player, "You may not man an auxiliary console with missiles equipped."); return; } if (HasFlag(type, HS_WIRETAP)) con->type = HS_OPS; else if (HasFlag(type, HS_CAPACITOR)) con->type = HS_ENG; else if (HasFlag(type, HS_CANNON | HS_EMITTER | HS_WEAPON)) con->type = HS_GUN; else con->type = HS_CIV; } else { /* this is a nav console */ /* no cans, caps or taps */ if (HasFlag(type, HS_CANNON)) { clear_weapon(pri); clear_weapon(sec); notify(player, "You may not man a navigation console with a cannon equipped."); return; } } /* the equipment slots check out, and the console has been set to the appropriate type, if needed */ if (prompt) { *prompt = HasFlag(atr_parse_integer(player, "HSPROMPT_FREQUENCY", 1), HS_PROMPT_FREQUENCY); FlagOn(*prompt, atr_parse_flags(player, hs_prompt_flags, "HSPROMPT_FLAGS")); } manning = get_console(player); if (manning != NOTHING) { manner = get_user(manning); if (manner == player) { con = find_console(manning); if (con) { load_weapon(manning, &(con->primary), HS_PRIMARY); load_weapon(manning, &(con->secondary), HS_SECONDARY); } set_user(manning, NOTHING); notify(player, tprintf("You unman the %s.", Name(manning))); notify_except(manning, Location(manning), player, tprintf("%s unmans the %s.", Name(player), Name(manning)), 0); } } /* set the HSPACE attribute in case something was fishy */ if (!IsSim(ship->objnum)) { atr_add(player, "HSPACE", unparse_dbref(ship->objnum), hs_options.space_wiz, 0); } set_user(console, player); execute_trigger(console, "AMAN", ship); if (con) { notify(player, tprintf("You man the %s (%s%s%s).", Name(console), ANSI_HILITE, STR(hs_console_types, con->type), ANSI_NORMAL)); notify_except(console, Location(console), player, tprintf("%s mans the %s (%s%s%s).", Name(player), Name(console), ANSI_HILITE, STR(hs_console_types, con->type), ANSI_NORMAL), 0); } else { notify(player, tprintf("You man the %s.", Name(console))); notify_except(console, Location(console), player, tprintf("%s mans the %s.", Name(player), Name(console)), 0); } }