/* $Id: keyring.c,v 1.666 2004/09/20 10:49:49 shrike Exp $ */ /************************************************************************************ * Copyright 2004 Astrum Metaphora consortium * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * * * ************************************************************************************/ /************************************************************************************ * Original eyring [C] 2002 Petr [Dingo] Dvorak <dingo@texoma.net> * * * * Written for Anime Planet MUD [animeplanet.genesismuds.com:3333 ] * ************************************************************************************/ #include <sys/types.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" #include "db/db.h" extern char *format_obj_to_char(OBJ_DATA *obj, CHAR_DATA *ch, bool fShort); KEY_DATA * new_key(void) { KEY_DATA * key; key = calloc(1,sizeof(*key)); VALIDATE(key); return key; } void free_key(KEY_DATA * key) { if (!key || !IS_VALID(key)) return; key->next = NULL; key->index = NULL; INVALIDATE(key); free(key); return; } // adds key to the keyring int add_key(OBJ_DATA * keyring, OBJ_DATA * key) { KEY_DATA * nkey; int i; if (!keyring) return KEYRING_NO_KEYRING; if (!key) return KEYRING_NO_KEY; if (!IS_VALID(keyring)) return KEYRING_INVALID_KEYRING; if (!IS_VALID(key)) return KEYRING_INVALID_KEY; i = 0; for (nkey = keyring->keys; nkey != NULL; nkey = nkey->next) { i++; if (nkey->index == key->pIndexData) return KEYRING_KEY_DUP; //TODO: May be allow dups keys } if( i >= keyring->value[0]) return KEYRING_MAX_REACHED; if ((IS_OBJ_STAT(key, ITEM_NODROP) || IS_OBJ_STAT(key, ITEM_NOREMOVE))) return KEYRING_CURSED; nkey = new_key(); nkey->index = key->pIndexData; nkey->next = keyring->keys; keyring->keys = nkey; obj_from_char(key); extract_obj(key); return KEYRING_OK; } int remove_key(CHAR_DATA * ch, OBJ_DATA * keyring, char * name) { KEY_DATA * key; KEY_DATA * key_next; if (!keyring) return KEYRING_NO_KEYRING; if (!keyring->keys) return KEYRING_NO_KEY; if (!name) return KEYRING_INVALID_NAME; if (name[0] == '\0') return KEYRING_INVALID_NAME; // let's find the key for (key = keyring->keys; key != NULL; key = key_next) { key_next = key->next; // check the name if (key && key->index->name && !str_prefix(name, key->index->name)) { OBJ_DATA *phys_key; phys_key = create_obj(key->index,key->index->level); obj_to_char(phys_key, ch); if (keyring->keys == key) keyring->keys = key->next; else { KEY_DATA *prev; for (prev = keyring->keys; prev != NULL; prev = prev->next) { if (prev->next == key) { // drop the key from the ring; prev->next = key->next; break; } } } free_key(key); return KEYRING_OK; } } return KEYRING_NO_REMKEY; } void save_keyring(FILE * fp, OBJ_DATA * obj) { KEY_DATA * keys; if (!obj || !obj->keys) return; fprintf(fp, "Keyring "); for (keys = obj->keys; keys != NULL; keys = keys->next) { if (keys->index->vnum) fprintf(fp, "%d ", keys->index->vnum); } // save -1 on the end of the list to terminate it fprintf(fp,"-1\n\r"); return; } void load_keyring(FILE * fp, OBJ_DATA * obj) { int vnum = 0; KEY_DATA * nkey; do { vnum = fread_number(fp); if (vnum > 0) { nkey = new_key(); nkey->index = get_obj_index(vnum); nkey->next = obj->keys; obj->keys = nkey; } } while (vnum > 0); return; } void list_keys(CHAR_DATA * ch, OBJ_DATA * keyring) { KEY_DATA * key; char buf[MAX_STRING_LENGTH]; //char * buf; if (keyring == NULL) return; if (!keyring->keys) { char_act("The keyring is empty.",ch); return; } char_act("\n\rThe keyring contains the following keys:\n\r",ch); for (key = keyring->keys; key != NULL; key = key->next) { buf[0] = '\0'; if (IS_IMMORTAL(ch)) char_printf(ch,"{D[{C%5.5d{D]{x",key->index->vnum); char_printf(ch," %s.\n\r", key->index->short_descr ? mlstr_val(key->index->short_descr, ch->lang) : "Unknown"); } return; } OBJ_DATA * find_keyring(CHAR_DATA * ch) { OBJ_DATA *obj; // search players inventory for keyring object for (obj = ch->carrying; obj != NULL; obj = obj->next_content) { if ((can_see_obj(ch, obj)) && obj->pIndexData->item_type == ITEM_KEYRING) return obj; } return NULL; } void keyring_message(int message, CHAR_DATA * ch, OBJ_DATA * key) { switch (message) { case KEYRING_OK: // everything ok .. what are we doing here ? return; break; case KEYRING_NO_KEYRING: // no keyring char_act("You don't have a keyring, go buy one.",ch); break; case KEYRING_NO_KEY: // no key char_act("You don't have that key.",ch); break; case KEYRING_NO_REMKEY: // no key on keyring char_act("You don't have that key on your keyring.",ch); break; case KEYRING_KEY_DUP: char_printf(ch, "You already have %s on your keyring.\n\r",mlstr_val(key->short_descr, ch->lang)); break; case KEYRING_MAX_REACHED: char_act("You already have max keys on your keyring.",ch); break; case KEYRING_CURSED: char_act("You cannot add cursed key on your keyring.",ch); break; case KEYRING_INVALID_NAME: case KEYRING_INVALID_KEYRING: case KEYRING_INVALID_KEY: default: char_act("Something gone horribly wrong, please tell the nearest immortal.",ch); break; } return; } void do_keyring(CHAR_DATA * ch, const char *argument) { OBJ_DATA * keyring = NULL; OBJ_DATA * key = NULL; char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; int message = KEYRING_OK; const char *msg; keyring = find_keyring(ch); if (!keyring) { keyring_message(KEYRING_NO_KEYRING,ch,NULL); return; } // no arguments ? just show list of the keys on the keyring then. if (argument[0] == '\0') { // yes i know, this is really filthy way to do this, but this way it // will show the same stuff like if people examine normal object // every mud is little different :) do_examine(ch, keyring->name); return; } argument = one_argument(argument, arg1, sizeof(arg1)); // command - add | remove argument = one_argument(argument, arg2, sizeof(arg2)); // key name if (arg2[0] == '\0') { char_act("You must specify the name of the key you wish to add or remove.", ch); return; } if (is_name(arg1, "add")) { key = get_obj_carry(ch, arg2); if (!key) { char_act("You don't have that key.", ch); return; } if (key->pIndexData->item_type != ITEM_KEY) { char_act("That is not a key!", ch); return; } msg = mlstr_val(key->short_descr, ch->lang); message = add_key(keyring, key); if (!message) { act_puts("$n adds $p on $s keyring.", ch, key, NULL, TO_ROOM, POS_RESTING); char_printf(ch, "You added %s on your keyring.\n\r", msg); } else { keyring_message(message,ch,key); } } else if (is_name(arg1, "remove")) { message = remove_key(ch, keyring, arg2); if (!message) { act_puts("$n removes a key from $s keyring.", ch, NULL, NULL, TO_ROOM, POS_RESTING); act_puts("You removed a key from your keyring.", ch, NULL, NULL, TO_CHAR, POS_RESTING); } else { keyring_message(message,ch,NULL); } } else { char_act("What exactly do you want to do with the keyring ?", ch); return; } return; }