/**************************************************************************/ // lockers.cpp - dawn locker system, written Feb 2002 by Kal /*************************************************************************** * The Dawn of Time v1.69r (c)1997-2004 Michael Garratt * * >> A number of people have contributed to the Dawn codebase, with the * * majority of code written by Michael Garratt - www.dawnoftime.org * * >> To use this source code, you must fully comply with the dawn license * * in licenses.txt... In particular, you may not remove this copyright * * notice. * **************************************************************************/ #include "include.h" #include "lockers.h" #include "ictime.h" // Locker implementation notes: // * the content of all lockers are stored in a single flat file, // depending on how popular the lockers are, it may make sense to // save lockers based on roomvnum... but for now I haven't bothered. /**************************************************************************/ lockers_object *lockers; bool lockers_referenced; // if this is true, the lockers will be saved next tick /**************************************************************************/ lockers_object::lockers_object() { memset(hash, 0, sizeof(hash)); }; /**************************************************************************/ locker_data *lockers_object::get_first(int roomvnum) { return hash[roomvnum%LOCKER_HASH_KEY]; }; /**************************************************************************/ // return the locker container object OBJ_DATA *lockers_object::find_locker_object(char_data *ch, bool display_messages, int number) { locker_data *locker; locker=find_locker(ch, display_messages, number); if(locker){ locker_data_of_last_found_locker_object=locker; return locker->locker_object; } locker_data_of_last_found_locker_object=NULL; return NULL; } /**************************************************************************/ locker_data *lockers_object::find_locker_data(char *owner, int roomvnum, int number) { locker_data *locker; // scan thru the list of lockers to find one for(locker=get_first(roomvnum); locker; locker=locker->next_locker){ if(locker->roomvnum!=roomvnum){ continue; } if(number){ if(number!=locker->number){ continue; } }else{ // no number specified, looking for the owners locker if(str_cmp(owner, locker->owner)){ continue; } } return locker; } return NULL; } /**************************************************************************/ locker_data *lockers_object::find_locker(char_data *ch, bool display_messages, int number) { if(!lockers->room_has_lockers(ch->in_room)){ if(display_messages){ ch->println("This room doesn't have any lockers."); } return NULL; } if(IS_NPC(ch)){ ch->println("NPC's can't access lockers."); return NULL; } if(GAMESETTING3(GAMESET3_LOCKERS_DISABLED)){ ch->println("The locker system is currently disabled."); return NULL; } // find a particular locker locker_data *locker; locker=find_locker_data(ch->name, ch->in_room_vnum(), number); if(locker){ lockers_referenced=true; locker->last_accessed=current_time; return locker; } if(display_messages){ if(number){ ch->printlnf("Couldn't find rented locker%d in this room.", number); }else{ ch->println("You don't own a locker in this room."); } } return NULL; } /**************************************************************************/ int lockers_object::count_used_lockers_in_room(int roomvnum) { int count=0; locker_data *locker; // scan thru the list of lockers counting the matches for(locker=get_first(roomvnum); locker; locker=locker->next_locker){ if(locker->roomvnum!=roomvnum){ continue; } count++; } return count; } /**************************************************************************/ // return true if room player is in has lockers bool lockers_object::room_has_lockers(ROOM_INDEX_DATA * room) { if( !room || !room->lockers || !room->lockers->initial_rent) { return false; } return true; } /**************************************************************************/ // when a player starts renting a locker void lockers_object::start_rent(char_data *ch, int locker_number) { if(!lockers->room_has_lockers(ch->in_room)){ ch->println("Lockers don't appear to be available in this room."); return; } if(IS_NPC(ch)){ ch->println("NPC's can't rent lockers."); return; } if(GAMESETTING3(GAMESET3_LOCKERS_DISABLED)){ ch->println("The locker system is currently disabled."); return; } if(find_locker(ch,false, 0)){ ch->println("You already own a locker in this room."); return; } if( ch->in_room->lockers->weight<1 || ch->in_room->lockers->capacity<1) { ch->wrapln("The lockers in this room are incorrectly setup, the locker " "weight and capacity must be greater than zero, talk to the admin."); return; } if(count_used_lockers_in_room(ch->in_room_vnum())>= ch->in_room->lockers->quantity){ ch->println("There are no more lockers available in this room for rent."); return; } if(locker_number>ch->in_room->lockers->quantity){ ch->printlnf("The locker numbering doesn't go as high as %d in this room.", locker_number); return; } if(locker_number){ locker_data *l=find_locker_data("", ch->in_room_vnum(), locker_number); if(l){ ch->printlnf("Locker %d is already taken.", locker_number); return; } } if(ch->gold<ch->in_room->lockers->initial_rent){ ch->printlnf("The initial rent for lockers in this room cost %d gold... you only have %ld.", ch->in_room->lockers->initial_rent, ch->gold); return; } // create a new locker locker_data *locker=new locker_data; locker->owner=str_dup(ch->name); locker->access=str_dup(""); locker->label=str_dup(ch->short_descr); locker->roomvnum=ch->in_room_vnum(); if(locker_number){ locker->number=locker_number; }else{ locker->number=get_next_free_locker_number(locker->roomvnum); } locker->paid_until=current_time+ICTIME_IRLSECS_PER_MONTH; // create a locker object for the new locker obj_data *o; o=create_object(get_obj_index(OBJ_VNUM_DUMMY)); replace_string(o->name, FORMATF("locker%d", locker->number)); replace_string(o->short_descr, FORMATF("locker %d", locker->number)); replace_string(o->description, FORMATF("locker %d is here", locker->number)); o->item_type = ITEM_CONTAINER; o->extra_flags = OBJEXTRA_NOPURGE | OBJEXTRA_BURN_PROOF | OBJEXTRA_NO_DEGRADE | OBJEXTRA_NO_RESTRING; o->extra2_flags = OBJEXTRA2_NODECAY | OBJEXTRA2_NOSELL | OBJEXTRA2_NOQUEST | OBJEXTRA_NOLOCATE; o->wear_flags = OBJWEAR_NO_SAC; o->weight = 0; o->cost = 0; o->level = 1; o->condition = 100; replace_string(o->material, "metal"); o->timer = 0; o->absolute_size= 0; o->relative_size= 0; o->ospec_fun = NULL; o->attune_id = 0; o->attune_flags = 0; o->attune_modifier= 0; o->attune_next = 0; o->extra_descr=NULL; o->value[0]=ch->in_room->lockers->weight; // container flags if(ch->in_room->lockers->pick_proof==3){ o->value[1]=CONT_CLOSEABLE | CONT_PICKPROOF | CONT_LOCKER; }else if(ch->in_room->lockers->pick_proof==2 && number_range(1,2)==1){ // 50% chance of getting a pick proof locker if set to random o->value[1]=CONT_CLOSEABLE | CONT_PICKPROOF | CONT_LOCKER; }else{ o->value[1]=CONT_CLOSEABLE | CONT_LOCKER; } o->value[2]=0; // key vnum o->value[3]=ch->in_room->lockers->capacity; o->value[4]=0; // weight multiplier // link the locker object into the particular room hosting the locker o->in_room=ch->in_room; locker->locker_object=o; // put the new locker in the hash bucket based on room vnum locker->next_locker=hash[locker->roomvnum%LOCKER_HASH_KEY]; hash[locker->roomvnum%LOCKER_HASH_KEY]=locker; ch->printlnf("You start renting locker %d for %d gold.", locker->number, ch->in_room->lockers->initial_rent); ch->gold-=ch->in_room->lockers->initial_rent; ch->println("hint: don't forget to close and lock your locker when you aren't using it."); lockers_referenced=true; locker->last_accessed=current_time; } /**************************************************************************/ // pay one IC year worth of rent void lockers_object::pay_rent(char_data *ch, int locker_number) { if(!lockers->room_has_lockers(ch->in_room)){ ch->println("Lockers don't appear to be available in this room."); return; } if(IS_NPC(ch)){ ch->println("NPC's can't rent lockers."); return; } if(GAMESETTING3(GAMESET3_LOCKERS_DISABLED)){ ch->println("The locker system is currently disabled."); return; } locker_data *l=find_locker(ch,true, locker_number); if(!l){ return; } if(l->paid_until> current_time + (3*ICTIME_IRLSECS_PER_YEAR)){ ch->println("You can't pay more than 3 IC years in advance."); return; } if(ch->gold<ch->in_room->lockers->ongoing_rent){ ch->printlnf("The ongoing rent for lockers in this room cost %d gold... you only have %ld.", ch->in_room->lockers->ongoing_rent, ch->gold); return; } ch->printlnf("You pay %d gold for an additional IC year worth of rent for your locker %d.", ch->in_room->lockers->ongoing_rent, l->number); l->paid_until+=ICTIME_IRLSECS_PER_YEAR; ch->gold-=ch->in_room->lockers->ongoing_rent; ch->printlnf("Your locker rent is now paid until %s (%.24s)", get_shorticdate_from_time(l->paid_until, "", 0), ctime(&l->paid_until)); if(l->locker_object){ SET_BIT(l->locker_object->value[1],CONT_CLOSEABLE); } ch->println("note: if your locker is not accessed for two IRL months, it will be automatically purged"); lockers_referenced=true; l->last_accessed=current_time; } /**************************************************************************/ GIO_START(locker_data) GIO_INT(roomvnum) GIO_SHINT(number) GIO_STR(owner) GIO_STR(access) GIO_STR(label) GIO_LONG(paid_until) GIO_LONG(last_accessed) GIO_FINISH_STRDUP_EMPTY /**************************************************************************/ void lockers_object::lockers_save_db() { if(GAMESETTING3(GAMESET3_LOCKERS_DISABLED)){ return; } if(!lockers_referenced){ return; } locker_data *locker; char write_filename[MSL]; sprintf(write_filename,"%s.write", LOCKERS_FILE); // find a free write filename - so if something stuffed up on // the write, we don't go over it. if(file_exists(write_filename)){ for(int i=0; i<20; i++){ sprintf(write_filename,"%s.write%d", LOCKERS_FILE, i); if(!file_exists(write_filename)){ break; } } } unlink(write_filename); logf("lockers_save_db(): saving lockers to %s.", write_filename); FILE *fp; if ( !( fp = fopen(write_filename, "w" ) ) ) { bugf("lockers_save_db(): fopen '%s' for write - error %d (%s)", write_filename, errno, strerror( errno)); exit_error( 1 , "lockers_save_db", "fopeen for write error"); } // loop thru the list of lockers saving them time_t expire_at=current_time-(60*60*24* game_settings->days_lockers_stored_for); for(int h=0; h<LOCKER_HASH_KEY; h++){ for(locker=hash[h]; locker; locker=locker->next_locker){ if(locker->last_accessed<expire_at) { logf("Not saving expired locker for %s in room %d.", locker->owner, locker->roomvnum); continue; } // lockers that are six IC months over due in rent (around 14 IRL days) if(locker->paid_until+(6*ICTIME_IRLSECS_PER_MONTH)<current_time){ logf("Not saving unpaid locker for %s in room %d.", locker->owner, locker->roomvnum); continue; } fprintf(fp,"#LOCKER\n"); { char *tstr=locker->access; locker->access=ltrim_string(rtrim_string(locker->access)); GIO_SAVE_RECORD(locker_data, locker, fp, NULL); locker->access=tstr; } if(locker->locker_object){ fwrite_obj( locker->locker_object, fp, 0, "O"); } fprintf(fp,"\n"); } } int bytes_written=fprintf(fp, "EOF~\n"); fclose( fp ); if(bytes_written != str_len("EOF~\n") ){ bugf("lockers_save_db(): fprintf to '%s' incomplete - error %d (%s)", write_filename, errno, strerror( errno)); bugf("Incomplete write of %s, write aborted - check diskspace!", write_filename); { autonote(NOTE_SNOTE, "lockers_save_db()", "Problems saving lockers database!", "code cc: imm", FORMATF("Incomplete write of %s, write aborted - check diskspace!\r\n", write_filename), true); } }else{ // maintain a backup { char buf[MIL]; sprintf(buf, "%s.giobak", LOCKERS_FILE); logf("lockers_save_db: Renaming old %s to %s", LOCKERS_FILE, buf); unlink(buf); rename(LOCKERS_FILE, buf); } logf("Renaming new %s to %s", write_filename, LOCKERS_FILE); unlink(LOCKERS_FILE); rename(write_filename, LOCKERS_FILE); } lockers_referenced=false; } /**************************************************************************/ void lockers_object::lockers_load_db() { int zero_numbered_lockers=0; // dynamically allocate object memory to itself if required if(!this){ lockers= new lockers_object; lockers->lockers_load_db(); return; } lockers_total_count=0; lockers_object_count=0; log_string("lockers_load_db(): loading lockers database."); lockers_referenced=false; locker_data *locker=NULL; if(!file_exists(LOCKERS_FILE)){ logf("lockers_load_db(): lockers database file '%s' not found.", LOCKERS_FILE); return; } FILE *fp; if ( !( fp = fopen(LOCKERS_FILE, "r" ) ) ) { bugf("lockers_load_db(): fopen '%s' for read - error %d (%s)", LOCKERS_FILE, errno, strerror( errno)); exit_error( 1 , "lockers_load_db", "fopeen for read error"); } bool morefile=true; locker_data *last_locker=NULL; // loop thru till we get the end of the file while (morefile && !feof(fp)) { char *readword= fread_word(fp); if (!str_cmp(readword, "EOF") || !str_cmp(readword, "EOF~")){ morefile=false; }else{ if(!str_cmp(readword, "#LOCKER")){ locker=new locker_data; // read in the data about the locker GIO_LOAD_RECORD(locker_data, locker, fp); // update the access text with spaces around the sides if(!IS_NULLSTR(locker->access)){ char *tstr=locker->access; locker->access=str_dup(FORMATF(" %s ", ltrim_string(rtrim_string(locker->access)))); free_string(tstr); } // confirm the locker number is unique if(locker->number){ if(find_locker_data("", locker->roomvnum, locker->number)){ bugf("Duplicated locker number %d for room %d, owner=%s, renumbering it.", locker->number, locker->roomvnum, locker->owner); locker->number=0; // set it to zero, and we can reallocate it later zero_numbered_lockers++; } }else{ zero_numbered_lockers++; } // put the new locker in the hash bucket based on room vnum locker->next_locker=hash[locker->roomvnum%LOCKER_HASH_KEY]; hash[locker->roomvnum%LOCKER_HASH_KEY]=locker; last_locker=locker; // initialise the locker object to NULL, as locker object will follow locker->locker_object=NULL; lockers_total_count++; }else if(!str_cmp(readword, "#O")){ OBJ_DATA *o=fread_obj( fp, LOCKERS_FILE); lockers_object_count++; if(o){ if(last_locker->locker_object){ obj_to_obj(o, last_locker->locker_object); }else{ last_locker->locker_object=o; last_locker->locker_object->in_room=get_room_index(last_locker->roomvnum); // if the locker rental has expired, open it, and make it uncloseable. if(last_locker->paid_until<current_time){ REMOVE_BIT(o->value[1],CONT_CLOSEABLE); REMOVE_BIT(o->value[1],CONT_CLOSED); REMOVE_BIT(o->value[1],CONT_LOCKED); } } } }else {// unexpected file format bugf("Unexpected fileformat in '%s' - found '%s' " "expecting '#LOCKER or #O'", LOCKERS_FILE, readword); write_shutdown_file(NULL); do_abort(); return; } } } fclose( fp ); // loop thru, allocating new locker numbers if required if(zero_numbered_lockers){ logf("%d zero numbered locker%s, allocating new numbers.", zero_numbered_lockers, zero_numbered_lockers==1?"":"s"); for(int h=0; h<LOCKER_HASH_KEY; h++){ for(locker=hash[h]; locker; locker=locker->next_locker){ if(!locker->number){ locker->number=get_next_free_locker_number(locker->roomvnum); if(locker->locker_object){ replace_string(locker->locker_object->name, FORMATF("locker%d", locker->number)); replace_string(locker->locker_object->short_descr, FORMATF("locker %d", locker->number)); replace_string(locker->locker_object->description, FORMATF("locker %d is here", locker->number)); } } } } } logf("Finished reading lockers from " LOCKERS_FILE ". (read in %d lockers, %d objects)", lockers_total_count, lockers_object_count); } /**************************************************************************/ // return the next available locker number in the room int lockers_object::get_next_free_locker_number(int roomvnum) { int looking_for; for(looking_for=1; ;looking_for++){ if(!find_locker_data("", roomvnum, looking_for)){ return looking_for; } } return -1; // shouldn't be able to get here } /**************************************************************************/ void lockers_object::info(char_data *ch, int locker_number) { ch->titlebar("LOCKERS"); int lock_in_use=lockers->count_used_lockers_in_room(ch->in_room_vnum()); ch->printlnf("This room has %d locker%s, of which %d %s in use.", ch->in_room->lockers->quantity, ch->in_room->lockers->quantity==1?"":"s", lock_in_use, lock_in_use==1?"is":"are"); ch->printlnf("It costs %d gold to start renting a locker (1 month rent inclusive).", ch->in_room->lockers->initial_rent); ch->printlnf("It costs %d gold per year for ongoing rental.", ch->in_room->lockers->ongoing_rent); ch->printlnf("New lockers can store up to %d lbs total.", ch->in_room->lockers->weight); ch->printlnf("The largest individual item which will fit in these lockers is %d lbs.", ch->in_room->lockers->capacity); locker_data *l; l=find_locker(ch, false, IS_IMMORTAL(ch)?locker_number:0); if(l){ if(is_exact_name(ch->name, l->owner)){ ch->titlebarf("YOUR LOCKER (#%d)", l->number); }else{ ch->titlebarf("LOCKER %d", l->number); } if(l->paid_until<current_time){ ch->println("YOUR LOCKER RENT HAS LAPSED, THEREFORE YOU CAN'T CLOSE IT!"); ch->printlnf("Your locker rent expired %s (%.24s)", get_shorticdate_from_time(l->paid_until, "", 0), ctime(&l->paid_until)); }else{ ch->printlnf("Your locker rent is paid until %s (%.24s)", get_shorticdate_from_time(l->paid_until, "", 0), ctime(&l->paid_until)); } if(l->locker_object){ ch->printlnf("Your locker is currently %s", !IS_SET(l->locker_object->value[1], CONT_CLOSED)?"open.": IS_SET(l->locker_object->value[1], CONT_LOCKED)?"locked.":"closed."); } if(IS_NULLSTR(ltrim_string(rtrim_string(l->access)))){ ch->println("Your lockers access settings are currently unset."); }else{ ch->println("Your lockers access settings are currently:"); ch->printlnf(" %s", l->access); } } ch->titlebar(""); } /**************************************************************************/ void lockers_object::look(char_data *ch) { ch->titlebar("ROOM LOCKERS"); int lock_in_use=lockers->count_used_lockers_in_room(ch->in_room_vnum()); ch->printlnf("This room has %d locker%s, of which %d %s in use.", ch->in_room->lockers->quantity, ch->in_room->lockers->quantity==1?"":"s", lock_in_use, lock_in_use==1?"is":"are"); locker_data *locker; int i; int max=0; int roomvnum=ch->in_room_vnum(); // find the maximum locker number for(locker=get_first(ch->in_room_vnum()); locker; locker=locker->next_locker){ if(locker->roomvnum==roomvnum){ max=UMAX(max, locker->number); } } for(i=0; i<=max; i++){ for(locker=get_first(roomvnum); locker; locker=locker->next_locker){ if(locker->roomvnum!=roomvnum){ continue; } if(locker->number!=i){ continue; } if(has_access(ch, locker)){ // highlight lockers player has access to ch->print("`W"); } if(locker->locker_object){ ch->printf("[%3d]`x %s %s`x", locker->number, IS_NULLSTR(locker->label)?"`S???`x":locker->label, !IS_SET(locker->locker_object->value[1],CONT_CLOSEABLE)?"<jammed open - expired lease>": !IS_SET(locker->locker_object->value[1], CONT_CLOSED)?"<open>":"<closed>"); }else{ ch->printlnf("Error: locker %d doesn't have a storage object!", locker->number); } if(IS_ADMIN(ch)){ ch->printf("`S %s%s", locker->locker_object && IS_SET(locker->locker_object->value[1], CONT_LOCKED)?"<locked>":"<UNLOCKED>", locker->locker_object && IS_SET(locker->locker_object->value[1], CONT_PICKPROOF)?"<pickproof>":""); ch->printlnf(" [%s] {%s}`x", locker->owner, locker->access); }else{ ch->println(""); } break; } } if(IS_ADMIN(ch)){ ch->println("`Sadminnote: [] = owner, {} = access`x"); } ch->titlebar(""); } /**************************************************************************/ void lockers_object::roomlist(char_data *ch, char *nametext) { char name[MIL]; one_argument(nametext, name); ch->titlebar("LOCKERS ROOMLIST"); bool namesearch=false; if(!IS_NULLSTR(name)){ namesearch=true; } int minvnum=1; int maxvnum=top_vnum_room; // now list all rooms with lockers in them int i; locker_data *locker; ROOM_INDEX_DATA *r; int h=0; bool found; for(i=minvnum; i<=maxvnum; i++){ r=get_room_index(i); if(r && r->lockers){ if(namesearch){ found=false; for(locker=get_first(i); locker; locker=locker->next_locker){ if(locker->roomvnum!=i){ continue; } if(!str_cmp(locker->owner, name) || is_exact_name(name, locker->access)){ found=true; break; } } if(!found){ continue; } } h++; ch->printlnf("%3d) [%s%s`x] (%2d/%2d) %s (%s%s`x)", h, colour_table[(i%14)+1].code, mxp_create_tagf(ch, "rmvnum", "%5d", i), lockers->count_used_lockers_in_room(i), r->lockers->quantity, r->name, colour_table[(r->area->vnum%14)+1].code, r->area->name); } } if(h==0){ if(namesearch){ ch->printlnf("There are no lockers in any rooms which '%s' has access to (note: clan access not checked).", name); }else{ ch->println("There are no rooms in the game with lockers configured."); } } ch->titlebar(""); } /**************************************************************************/ bool lockers_object::has_access(char_data *ch, locker_data *l) { if(!str_cmp(l->owner, ch->name) || is_exact_name(ch->name, l->access)){ lockers_referenced=true; l->last_accessed=current_time; return true; } // check clan access if(ch->clan){ if(is_exact_name(FORMATF("clan=%s", ch->clan->notename()), l->access)){ lockers_referenced=true; l->last_accessed=current_time; return true; } } return false; // they didn't have access } /**************************************************************************/ // admin deleting a particular locker bool lockers_object::has_access(char_data *ch, OBJ_DATA *locker_object) { if(IS_IMMORTAL(ch)){ return true; // imms always have access to lock/unlock all lockers } if(!locker_data_of_last_found_locker_object || locker_data_of_last_found_locker_object->locker_object!=locker_object) { // we dont bother searching for it, if we dont have the last // referenced object cached, we forget about it. return false; } if(IS_NPC(ch)){ return false; } if(IS_SET(ch->dyn,DYN_IS_BEING_ORDERED)){ // no access while being ordered return false; } return has_access(ch, locker_data_of_last_found_locker_object); } /**************************************************************************/ // remove access from a locker void lockers_object::remove_access(char_data *ch, char *argument, int locker_number) { locker_data *l; // find the locker l=find_locker(ch, true, locker_number); if(!l){ return; } if(!IS_ADMIN(ch) && str_cmp(ch->name, l->owner)){ ch->printlnf("You can't change the access settings of locker %d.", l->number); return; } char arg[MIL]; one_argument(argument, arg); smash_tilde(arg); if(has_colour(arg)){ ch->println("You can't use colour codes here."); return; } if(!is_exact_name(arg, l->access)){ ch->printlnf("'%s' doesn't have access to locker %d.", arg, l->number); ch->printlnf("Access is restricted to: %s", ltrim_string(rtrim_string(l->access))); return; } // remove them from the locker's access list l->access=string_replace_all(l->access, FORMATF(" %s ", arg), " "); l->access=string_replace_all(l->access, " ", " "); ch->printlnf("'%s' no longer has access to locker %d.", arg, l->number); ch->printlnf("Access is now restricted to:%s", l->access); } /**************************************************************************/ void lockers_object::changeowner(char_data *ch, char *argument, int locker_number) { locker_data *l; // find the locker l=find_locker(ch, true, locker_number); if(!l){ return; } ch->printlnf("locker %d owner changed from '%s' to '%s'", l->number, l->owner, argument); replace_string(l->owner, argument); lockers_referenced=true; l->last_accessed=current_time; } /**************************************************************************/ void lockers_object::changelabel(char_data *ch, char *argument, int locker_number) { locker_data *l; // find the locker l=find_locker(ch, true, locker_number); if(!l){ return; } ch->printlnf("locker %d label changed from '%s' to '%s'", l->number, l->label, argument); replace_string(l->label, argument); lockers_referenced=true; l->last_accessed=current_time; } /**************************************************************************/ void lockers_object::tempopen(char_data *ch, char *argument, int locker_number) { locker_data *l; // find the locker l=find_locker(ch, true, locker_number); if(!l){ return; } if(!l->locker_object){ ch->printlnf("For some reason, locker %d (%s) doesn't have a locker object!", l->number, l->owner); return; } ch->printlnf("LOCKER %d (%s) TEMPOPEN START:", l->number, l->owner); // backup the lockers open status int locker_flags=l->locker_object->value[1]; // open the locker the bit way REMOVE_BIT(l->locker_object->value[1],CONT_CLOSED); REMOVE_BIT(l->locker_object->value[1],CONT_LOCKED); // run the command interpret(ch, argument); // restore the lockers open status l->locker_object->value[1]=locker_flags; ch->printlnf("LOCKER %d (%s) TEMPOPEN END:", l->number, l->owner); lockers_referenced=true; l->last_accessed=current_time; } /**************************************************************************/ // grant access to a locker void lockers_object::grant_access(char_data *ch, char *argument, int locker_number) { locker_data *l; // find the locker l=find_locker(ch, true, locker_number); if(!l){ return; } if(!IS_ADMIN(ch) && str_cmp(ch->name, l->owner)){ ch->printlnf("You can't change the access settings of locker %d.", l->number); return; } char arg[MIL]; one_argument(argument, arg); smash_tilde(arg); if(has_colour(arg)){ ch->println("You can't use colour codes here."); return; } if(is_exact_name(arg, l->access)){ ch->printlnf("'%s' already has access to locker %d.", arg, l->number); ch->printlnf("Access is restricted to:%s", l->access); return; } // add them to the locker's access list if(str_len(l->access)> MIL){ ch->printlnf("Too many names listed with access to locker %d.", l->number); ch->printlnf("Access is restricted to:%s", l->access); return; } if(IS_NULLSTR(l->access)){ replace_string(l->access, FORMATF(" %s ", arg)); }else{ char *f=FORMATF("%s%s ", l->access, arg); replace_string(l->access, f); } ch->printlnf("access granted to '%s' for locker %d.", arg, l->number); ch->printlnf("Access is now restricted to: %s", l->access); } /**************************************************************************/ // admin deleting a particular locker void lockers_object::admin_delete(char_data *ch, int locker_number) { locker_data *l; // find the locker l=find_locker(ch, true, locker_number); if(!l){ return; } // we have the locker object, move all objects out of it onto the floor ch->printlnf("Locker %d data found...", l->number); obj_data *obj=l->locker_object; obj_data *obj_next_content; if(obj){ ch->println("Locker container object exists, moving objects to floor..."); for( obj=obj->contains; obj; obj = obj_next_content ){ obj_next_content=obj->next_content; obj_from_obj(obj); obj_to_room(obj, ch->in_room); ch->printlnf(" %s`x", format_obj_to_char(obj, ch, true)); } ch->println("Deallocating locker container object..."); l->locker_object->in_room=NULL; extract_obj(l->locker_object); l->locker_object=NULL; } ch->printlnf("Deallocating locker %d data...", l->number); // find the locker data's position in the list locker_data *prev=NULL; locker_data *node; for(node=get_first(l->roomvnum); node; node=node->next_locker){ if(l!=node){ prev=node; continue; } // we have found the locker, remove it from the listing if(prev){ prev->next_locker=l->next_locker; }else{ // first in the list hash[l->roomvnum%LOCKER_HASH_KEY]=l->next_locker; } // deallocate locker data ch->printlnf("Locker %d successfully removed.", l->number); delete l; return; } // shouldn't get here ch->printlnf("Couldn't find locker %d to remove!?!", l->number); return; } /**************************************************************************/ void lockers_object::postletter(char_data *ch, int locker_number) { obj_data *letter; letter= get_eq_char(ch,WEAR_HOLD); if( !letter || letter->item_type != ITEM_PARCHMENT ) { ch->println( "You must be holding the letter you want to post in your hands to post it." ); return; } locker_data *l; // find the locker l=find_locker(ch, true, locker_number); if(!l){ return; } if(!l->locker_object){ ch->printlnf("For some reason locker %d doesn't have a locker object, " "please report this to the admin.", l->number); return; } // note: by design there is no limit on the number of letters // you can put in a locker. This way a room can be setup as postboxes, // where the weight and capacity of the lockers are 1... not fitting any // decent sized object. obj_from_char(letter); obj_to_obj(letter, l->locker_object); act("You post a letter into $p.", ch, l->locker_object, NULL, TO_CHAR ); act("$n posts a letter into $p.",ch,l->locker_object,NULL,TO_ROOM); } /**************************************************************************/ void locker_notes(char_data *ch) { ch->titlebar("LOCKER NOTES"); ch->println("syntax: buy locker - purchase the first available locker in the room."); ch->println("syntax: buy locker5 - attempt to purchase locker number 5 in the room."); ch->println("syntax: look lockers - list all lockers in the room."); ch->println("syntax: look in locker - look inside your locker."); ch->println("syntax: look in locker2 - look inside locker2."); ch->println("syntax: lock loc - close and lock your locker."); ch->println("syntax: lock locker23 - close and lock locker 23 (if you have lock access)."); ch->println("syntax: open loc - unlock and open your locker."); ch->println("syntax: open locker8 - unlock (if you have lock access) and open locker 8."); ch->println("syntax: put bread in locker5 - put the bread in locker 5 (assuming it is open)."); ch->titlebar(""); } /**************************************************************************/ void do_lockers(char_data *ch, char *argument) { char arg[MIL]; int locker_number=0; if(GAMESETTING3(GAMESET3_LOCKERS_DISABLED)){ ch->println("The locker system is currently disabled."); return; } smash_tilde(argument); // no ordering to access lockers if(IS_SET(ch->dyn,DYN_IS_BEING_ORDERED)){ if(ch->master){ ch->master->println( "Not going to happen."); } return; } if(IS_NULLSTR(argument)){ ch->titlebar("LOCKER COMMANDS"); ch->println("syntax: locker notes - display notes on using lockers"); ch->println("syntax: locker # postletter - post the letter you are holding into locker #"); ch->println("syntax: locker info - show info on lockers in the room, and your rent status"); ch->println("syntax: locker payrent - pay an IC years worth of rent"); ch->println(""); ch->println("== access commands for those renting a locker:"); ch->println("syntax: locker grantaccess <name> - give <name> access to locker"); ch->println("syntax: locker grantaccess clan=<clan_notename>"); ch->println(" - give all members in clan <clan_notename> access to locker"); ch->println("syntax: locker removeaccess <name> - remove access to locker from <name>"); ch->println(""); if(IS_ADMIN(ch)){ ch->println("== admin only locker commands:"); ch->println("syntax: locker roomlist [name] - list rooms with lockers in them [for name]"); ch->println("syntax: locker changeowner - changes the owner of a given locker"); ch->println("syntax: locker changelabel <label text> - change a label on locker");// ch->println("syntax: locker # delete - delete a locker, any contents are moved to ground"); ch->println("syntax: locker # tempopen <command> - flags a locker open for <command>"); ch->println(" e.g. locker 5 tempopen look in locker5"); ch->println(""); } ch->println("note: # = locker number, if you omit this number your locker will be used"); ch->titlebar(""); return; } argument=one_argument(argument, arg); // support the optional locker number if(is_number(arg)){ locker_number=atoi(arg); if(locker_number<1){ ch->println("The locker numbering starts at 1."); return; } // shift arguments left one argument=one_argument(argument, arg); } // admin room list command, can be used in any room if(IS_ADMIN(ch)){ if(!str_prefix(arg, "roomlist")){ lockers->roomlist(ch, argument); return; } } if(!str_prefix(arg, "notes")){ locker_notes(ch); return; } // all commands below here must be used in a room with lockers if(!lockers->room_has_lockers(ch->in_room)){ ch->println("This room doesn't have any lockers."); return; } if(IS_NPC(ch)){ ch->println("NPC's can't access lockers."); return; } if(!str_prefix(arg, "info")){ lockers->info(ch, locker_number); return; } if(!str_prefix(arg, "look")){ lockers->look(ch); return; } if(!str_cmp(arg, "grantaccess")){ if(IS_NULLSTR(argument)){ ch->println("You need to specify a name after the grantaccess command."); return; } lockers->grant_access(ch, argument, locker_number); return; } if(!str_cmp(arg, "removeaccess")){ if(IS_NULLSTR(argument)){ ch->println("You need to specify a name after the removeaccess command."); return; } lockers->remove_access(ch, argument, locker_number); return; } if(!str_cmp(arg, "postletter")){ if(locker_number==0){ ch->println("specify the locker number you want to post into... e.g. 'locker 5 postletter'"); return; } lockers->postletter(ch, locker_number); return; } if(!str_cmp(arg, "startrent")){ lockers->start_rent(ch, locker_number); return; } if(!str_cmp(arg, "payrent")){ if(!IS_IMMORTAL(ch) && locker_number!=0){ ch->println("You can not pay the rent on someone elses locker... just type 'locker payrent' to pay your rent."); return; } lockers->pay_rent(ch, locker_number); return; } // admin only commands if(IS_ADMIN(ch)){ if(!str_cmp(arg, "delete")){ lockers->admin_delete(ch, locker_number); return; } if(!str_cmp(arg, "changeowner")){ lockers->changeowner(ch, argument, locker_number); return; } if(!str_cmp(arg, "changelabel")){ lockers->changelabel(ch, argument, locker_number); return; } if(!str_cmp(arg, "tempopen")){ lockers->tempopen(ch, argument, locker_number); return; } } ch->printlnf("Unrecognised lockers option '%s'", arg); do_lockers(ch,""); } /**************************************************************************/ /**************************************************************************/