/* * access.cpp * This file contains the routines necessary to access arrays * ____ _ * | _ \ ___ __ _| |_ __ ___ ___ * | |_) / _ \/ _` | | '_ ` _ \/ __| * | _ < __/ (_| | | | | | | \__ \ * |_| \_\___|\__,_|_|_| |_| |_|___/ * * Permission to use, modify and distribute is granted via the * Creative Commons - Attribution - Non Commercial - Share Alike 3.0 License * http://creativecommons.org/licenses/by-nc-sa/3.0/ * * Copyright (C) 2007-2012 Jason Mitchell, Randi Mitchell * Contributions by Tim Callahan, Jonathan Hseu * Based on Mordor (C) Brooke Paul, Brett J. Vickers, John P. Freeman * */ #include "mud.h" #include "calendar.h" // Stats char stat_names[][4] = { "STR", "DEX", "CON", "INT", "PTY", "CHA" }; char* getStatName(int stat) { stat = tMIN<int>(tMAX<int>(stat - 1, 0), MAX_STAT); return(stat_names[stat]); } char save_names[][4] = { "LCK", "POI", "DEA", "BRE", "MEN", "SPL" }; char* getSaveName(int save) { save = tMIN<int>(tMAX<int>(save, 0), MAX_SAVE-1); return(save_names[save]); } // // object // char object_type[][20] = { "error", "error", "error", "instrument", "herb", "weapon", "piece of armor", "potion", "scroll", "magic wand", "container", "money", "key", "light source", "miscellaneous item", "song scroll", "poison", "bandage", "ammo", "quiver", "lottery ticket", "unknown item" }; // // class // char class_str[][16] = { "None", "Assassin", "Berserker", "Cleric", "Fighter", "Mage", "Paladin", "Ranger", "Thief", "Pureblood", "Monk", "Death Knight", "Druid", "Lich", "Werewolf", "Bard", "Rogue", "Builder", "Unused", "Caretaker", "Dungeonmaster" }; char class_abbrev[][8] = { "Assn", "Bers", "Cleric", "Ftr", "Mage", "Pal", "Rang", "Thief", "Vamp", "Monk", "Dknght", "Druid", "Lich", "Were", "Bard", "Rogue", "Build", "Crt", "CT", "DM" }; char shortClassAbbrev[][8] = { "A", "Be", "Cl", "F", "M", "P", "R", "T", "Va", "Mo", "Dk", "Dr", "L", "W", "Bd", "Ro", "Bu", "Cr", "CT", "DM" }; // // mobs // char mob_trade_str[][16] = { "None", "Smithy", "Banker", "Armorer", "Weaponsmith", "Merchant", "Training Perm" }; char mob_skill_str[][16] = { "Horrible", "Poor", "Fair", "Decent", "Average", "Talented", "Very Good", "Exceptional", "Master", "Grand Master", "Godlike" }; unsigned int permAC[30] = { 25, 70, 110, 155, 200, 245, 290, 335, 380, 425, 470, 510, 535, 560, 580, 600, 620, 645, 670, 690, 710, 730, 760, 780, 820, 870, 890, 910, 960, 1000 }; // // language // char lang_color[LANGUAGE_COUNT][3] = { "^m", // Alien "^c", // Dwarven "^g", // Elven "^c", // Halfling "^c", // Common "^y", // Orcish "^y", // Giantkin "^b", // Gnomish "^g", // Trollish "^y", // Ogrish "^m", // Dark-Elven (Drow) "^g", // Goblinoid "^y", // Minotaur "^b", // Celestial "^c", // Kobold "^r", // Infernal "^y", // Schnai "^r", // Kataran "^g", // Druidic "^y", // Wolfen "^m", // Thieves' Cant "^m", // Arcanic (Mages/Lich) "^m", // Abyssal "^r", // Tiefling }; char language_adj[][32] = { "an alien language", "dwarven", "elven", "halfling", "common", "orcish", "giantkin", "gnomish", "trollish", "ogrish", "darkelf", "goblinoid", "minotaur", "celestial", "kobold", "infernal", "barbarian", "kataran", "druidic", "wolfen", "thieves' cant", "arcanic", "abyssal", "tiefling" }; char language_verb[][3][24] = { // Unknown (alien) {"blab", "mysteriously say", "rapidly gibber"}, // Dwarven {"mutter", "utter", "grumble"}, // Elven {"say", "speak", "eloquently say"}, // Halfling {"say", "speak", "utter"}, // Common {"say", "speak", "say"}, // Orcish {"grunt", "squeal", "snort"}, // Giantkin {"boom", "speak", "say"}, // Gnomish {"say", "speak", "utter"}, // Trollish*/ {"snarl", "spit", "gutterly cough"}, // Ogrish {"grunt", "snarl", "boom"}, // Dark elven {"snide", "sneer", "rapidly speak"}, // Goblinoid {"sputter", "snort", "cough"}, // Minotaur {"snort", "grunt", "speak"}, // Celestial {"speak", "sing", "eloquently speak"}, // Kobold {"bark", "snort", "growl"}, // Infernal {"snarl", "growl", "gutterly speak"}, // Schnai {"growl", "snarl", "sneer"}, // Kataran {"purr", "growl", "spit"}, // Druidic {"mutter", "say", "sound"}, // Wolfen {"loudly bark", "growl", "bay"}, // Thieves' Cant {"gesture", "allude", "mumble"}, // Arcanic {"gibber", "quickly speak", "chatter"}, // Abyssal {"growl", "snarl", "cough"}, // Tiefling {"jabber", "spit", "snarl"} }; // // other // char save_str[MAX_SAVE_COLOR][20] = { "Normal", "Good", "Above Average", "Resistant", "Excellent", "Incredible", "Amazing", "Superb", "Impervious", "Unbelievable", "Immune" }; char save_color[MAX_SAVE_COLOR] = { 'g', 'c', 'r', 'y', 'm', 'B', 'G', 'C', 'R', 'Y', 'M'}; // Jakar //{ "Tinkerer", "Haggler", "Inventor", "Merchant Priest", "Divine Trademaster", // "Emerald Bishop", "Diamond Patriarch", "Golden Cardinal", "25-27","28-30"}, // Jakar //{ "Tinkerer", "Haggler", "Inventor", "Merchant Priestess", "Divine Trademistress", // "Emerald Prelate", "Diamond Matriarch", "Golden Lama", "25-27","28-30"} char scrollDesc [][10][20] = { // Earth Realm {"dirty", "earthen", "sandy", "dusty", "terran", "hardened", "unbreakable", "petrified", "metallic", "earthy"}, // Air Realm {"whistling", "airy", "translucent", "whisping", "windy", "transparent", "invisible", "flying", "soaring", "breathing"}, // Fire Realm {"scorched", "burning", "red-hot", "blackened", "burnt", "heated", "magma", "firey", "seething", "white-hot"}, // Water Realm {"watery", "waterlogged", "waterproof", "wet", "misty", "sea blue", "azurite", "seaweed", "saltwater", "coral"}, // Elec Realm {"crackling", "electric", "magnetic", "shocking", "electrostatic", "copper", "conductive", "sparking", "bipolar", "ozone"}, // Cold Realm {"freezing", "frosty", "icy", "arctic", "icicled", "dry ice", "frozen", "sublimating", "melting", "ice blue"} }; char scrollType [][2][20] = { // level 1 {"parchment","papyrus"}, // level 2 {"scroll","journal"}, // level 3 {"tablet","spellbook"}, // level 4 {"folio","volume"}, // level 5 {"cuneiform tablet","tome"}, // level 6 {"runed cloth","manual"} }; static char number[][15] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty", "twenty-one", "twenty-two", "twenty-three", "twenty-four", "twenty-five", "twenty-six", "twenty-seven", "twenty-eight", "twenty-nine", "thirty" }; //********************************************************************* // int_to_test() //********************************************************************* bstring intToText(int nNumber, bool cap) { bstring toReturn; // check for array bounds if(nNumber < 31 && nNumber >= 0) { toReturn = number[nNumber]; } else { toReturn = bstring(nNumber); } if(cap) toReturn[0] = up(toReturn[0]); return(toReturn); } bstring getOrdinal(int num) { bstring ordinal; char buff[32]; int last=0; ltoa(num, buff, 10); ordinal = buff; last = getLastDigit(num, 2); if(last > 10&& last < 14) ordinal += "th"; else { last = getLastDigit(num, 1); switch (last) { case 1: ordinal += "st"; break; case 2: ordinal += "nd"; break; case 3: ordinal += "rd"; break; default: ordinal += "th"; break; } } return(ordinal); } int get_perm_ac(int nIndex) { nIndex = MAX( 0, MIN(nIndex, 29 ) ); return(permAC[nIndex]); } //********************************************************************* // get_class_string() //********************************************************************* char *get_class_string(int nIndex) { // do bounds checking ASSERTLOG( nIndex >= 0 ); ASSERTLOG( nIndex < CLASS_COUNT ); nIndex = MAX( 0, MIN(nIndex, CLASS_COUNT - 1 ) ); return(class_str[nIndex]); } char* get_lang_color(int nIndex) { ASSERTLOG( nIndex >= 0 ); ASSERTLOG( nIndex < LANGUAGE_COUNT ); nIndex = MAX( 0, MIN(nIndex, LANGUAGE_COUNT-1 ) ); return(lang_color[nIndex]); } char *get_language_adj(int nIndex) { // do bounds checking ASSERTLOG( nIndex >= 0 ); ASSERTLOG( nIndex < LANGUAGE_COUNT ); nIndex = MAX( 0, MIN(nIndex, LANGUAGE_COUNT - 1 ) ); return(language_adj[nIndex]); } // language verb char *get_language_verb(int lang) { int num=0; ASSERTLOG( lang >= 0 ); ASSERTLOG( lang < LANGUAGE_COUNT ); num = mrand(1,3); lang = MAX(0, MIN(lang, LANGUAGE_COUNT-1)); return(language_verb[lang][num-1]); } //********************************************************************* // get_trade_string() //********************************************************************* char *get_trade_string(int nIndex) { // do bounds checking ASSERTLOG( nIndex >= 0 ); ASSERTLOG( nIndex < MOBTRADE_COUNT ); nIndex = MAX( 0, MIN(nIndex, MOBTRADE_COUNT) ); return(mob_trade_str[nIndex]); } //********************************************************************* // get_skill_string() //********************************************************************* char *get_skill_string(int nIndex) { // do bounds checking ASSERTLOG( nIndex >= 0 ); ASSERTLOG( nIndex < 11 ); nIndex = MAX( 0, MIN(nIndex, 10) ); return(mob_skill_str[nIndex]); } char *get_save_string(int nIndex) { // do bounds checking ASSERTLOG( nIndex >= 0 ); ASSERTLOG( nIndex < MAX_SAVE_COLOR ); nIndex = MAX( 0, MIN(nIndex, MAX_SAVE_COLOR-1 ) ); return(save_str[nIndex]); } char get_save_color(int nIndex) { ASSERTLOG( nIndex >= 0 ); ASSERTLOG( nIndex < MAX_SAVE_COLOR ); nIndex = MAX( 0, MIN(nIndex, MAX_SAVE_COLOR-1 ) ); return(save_color[nIndex]); } const char *get_mflag(int nIndex) { // do bounds checking ASSERTLOG( nIndex >= 0 ); ASSERTLOG( nIndex < MAX_MONSTER_FLAGS+1 ); nIndex = MAX( 0, MIN(nIndex, MAX_MONSTER_FLAGS ) ); // flags are offset by 1 nIndex++; return(gConfig->mflags[nIndex].name.c_str()); } const char *get_pflag(int nIndex) { // do bounds checking ASSERTLOG( nIndex >= 0 ); ASSERTLOG( nIndex < MAX_PLAYER_FLAGS+1 ); nIndex = MAX( 0, MIN(nIndex, MAX_PLAYER_FLAGS ) ); // flags are offset by 1 nIndex++; return(gConfig->pflags[nIndex].name.c_str()); } const char *get_rflag(int nIndex) { // do bounds checking ASSERTLOG( nIndex >= 0 ); ASSERTLOG( nIndex < MAX_ROOM_FLAGS+1 ); nIndex = MAX( 0, MIN(nIndex, MAX_ROOM_FLAGS ) ); // flags are offset by 1 nIndex++; return(gConfig->rflags[nIndex].name.c_str()); } const char *get_xflag(int nIndex) { // do bounds checking ASSERTLOG( nIndex >= 0 ); ASSERTLOG( nIndex < MAX_EXIT_FLAGS+1 ); nIndex = MAX( 0, MIN(nIndex, MAX_EXIT_FLAGS ) ); // flags are offset by 1 nIndex++; return(gConfig->xflags[nIndex].name.c_str()); } const char *get_oflag(int nIndex) { // do bounds checking ASSERTLOG( nIndex >= 0 ); ASSERTLOG( nIndex < MAX_OBJECT_FLAGS+1 ); nIndex = MAX( 0, MIN(nIndex, MAX_OBJECT_FLAGS ) ); // flags are offset by 1 nIndex++; return(gConfig->oflags[nIndex].name.c_str()); } char *getClassAbbrev(int nIndex) { // do bounds checking ASSERTLOG( nIndex >= 0 ); ASSERTLOG( nIndex < CLASS_COUNT ); nIndex = MAX( 0, MIN(nIndex, CLASS_COUNT - 1 ) ); return(class_abbrev[nIndex-1] ); } char *getClassName(Player* player) { static char classname[1024]; if(!player->getSecondClass()) return(get_class_string( player->getClass())); strcpy(classname, ""); strcpy(classname, getShortClassAbbrev( player->getClass() ) ); strcat(classname, "/"); strcat(classname, getShortClassAbbrev( player->getSecondClass() ) ); return(classname); } char *getShortClassAbbrev(int nIndex) { // do bounds checking ASSERTLOG( nIndex >= 0 ); ASSERTLOG( nIndex < CLASS_COUNT ); nIndex = MAX( 0, MIN(nIndex, CLASS_COUNT - 1 ) ); return(shortClassAbbrev[nIndex-1] ); } char *getShortClassName(const Player* player) { static char classname[1024]; if(!player->getSecondClass()) return(get_class_string(player->getClass())); strcpy(classname, ""); strcpy(classname, getShortClassAbbrev(player->getClass())); strcat(classname, "/"); strcat(classname, getShortClassAbbrev(player->getSecondClass())); return(classname); } //********************************************************************* // getTitle //********************************************************************* // This function returns a string with the player's character title in // it. The title is determined by looking at the player's class and // level. bstring Player::getTitle() const { std::ostringstream titleStr; int titlnum; if(title == "" || title == " " || title == "[custom]") { titlnum = (level - 1) / 3; if(titlnum > 9) titlnum = 9; if(cClass == CLERIC) titleStr << gConfig->getDeity(deity)->getTitle(level, getSex() == SEX_MALE); else titleStr << gConfig->classes[get_class_string(cClass)]->getTitle(level, getSex() == SEX_MALE); if(cClass2) { titleStr << "/"; if(cClass2 == CLERIC) titleStr << gConfig->getDeity(deity)->getTitle(level, getSex() == SEX_MALE); else titleStr << gConfig->classes[get_class_string(cClass2)]->getTitle(level, getSex() == SEX_MALE); } return(titleStr.str()); } else { return(title); } } bstring Player::getCustomTitle() const { return(title); } bstring Player::getTempTitle() const { return(tempTitle); } bool Player::canChooseCustomTitle() const { const std::map<int, PlayerTitle*>* titles=0; std::map<int, PlayerTitle*>::const_iterator it; const PlayerTitle* title=0; if(cClass == CLERIC) titles = &(gConfig->getDeity(deity)->titles); else titles = &(gConfig->classes[get_class_string(cClass)]->titles); it = titles->find(level); if(it == titles->end()) return(false); title = (*it).second; return(title && title->getTitle(getSex() == SEX_MALE) == "[custom]"); } void Player::setTitle(bstring newTitle) { title = newTitle; } void Player::setTempTitle(bstring newTitle) { tempTitle = newTitle; } //********************************************************************* // int_to_test() //********************************************************************* char *int_to_text(int nNumber) { static char strNum[15]; char *strReturn; // check for array bounds if(nNumber < 31 && nNumber >= 0) { strReturn = number[nNumber]; } else { sprintf(strNum, "%d", nNumber ); strReturn = strNum; } return(strReturn); } //********************************************************************* // get_quest_exp() //********************************************************************* long get_quest_exp(int nQuest) { // quests are 1 based and this array is zero based // so subtract one first nQuest--; nQuest = MAX(0, MIN(nQuest, numQuests ) ); return(gConfig->questTable[nQuest]->exp); } //********************************************************************* // get_quest_name() //********************************************************************* const char *get_quest_name(int nIndex) { // do bounds checking ASSERTLOG(nIndex >= -1); ASSERTLOG(nIndex < 64); nIndex = MAX(-1, MIN(nIndex, numQuests)); if(nIndex==-1) return("None"); if(nIndex >= numQuests) return("Unknown"); else return(gConfig->questTable[nIndex]->name); } //********************************************************************* // obj_type //********************************************************************* char *obj_type(int nType) { if(nType < 0) nType = 0; if(nType > MAX_OBJ_TYPE) nType = MAX_OBJ_TYPE; return(object_type[nType]); } char conjureTitles[][3][10][30] = { // earth { // weak { "lesser earth elemental", "marble mongoose", "rock ape", "earth spider", "giant badger", "steel snake", "golden fox", "giant rock worm", "glassteel golem", "earth demon" }, // normal { "giant mole", "obsidian worm", "mud sloth", "crystal wolf", "earth elemental", "granite elephant", "iron sentinel", "greater earth elemental", "steel tiger", "adamantium tiger" }, // buff { "pet rock", "sandman", "rock wolverine", "rock demon", "marble tiger", "earth devil", "crystal sentinel", "galeb duhr", "steel hydra", "adamantium dragon" } }, // air { // weak { "lesser air elemental", "wind snake", "wind rat", "zephyr cat", "wind imp", "aerial tiger", "cloud ogre", "silver eagle", "cloud giant", "winged elf lord" }, // normal { "giant wasp", "aerial vortex", "air sentinel", "winged cobra", "air elemental", "aerial stalker", "wind devil", "greater air elemental", "cloud drake", "djinn air lord" }, // buff { "wind bat", "baby griffon", "dust devil", "winged elf", "winged unicorn", "black pegasus", "djinn", "jade falcon", "ki-rin", "cloud giant wizard" } }, // fire { // weak { "lesser fire elemental", "giant firefly", "lesser fire demon", "fire mephit", "fire cat", "salamander", "firey skeleton warrior", "crimson lion", "fire drake", "lava raptor" }, // normal { "fire sphere", "fire snake", "fire beetle", "flame spider", "fire elemental", "firehawk", "fire angel", "greater fire elemental", "fire kraken", "phoenix" }, // buff { "burning bush", "fire asp", "flame sprite", "ruby serpent", "crimson iguana", "brimstone demon", "efretti", "horned fire devil", "fire giant shaman", "venerable red dragon" } }, // water { // weak { "lesser water elemental", "aquatic elf", "acidic blob", "vapor rat", "water weird", "fog beast", "white crocodile", "steam jaguar", "water-logged troll", "bronze dragon" }, // normal { "giant frog", "water imp", "mist devil", "water scorpion", "water elemental", "steam spider", "blood elemental", "greater water elemental", "acid devil", "water elemental lord" }, // buff { "mist rat", "creeping fog", "water mephit", "mist spider", "carp dragon", "giant water slug", "giant squid", "mist dragon", "kraken", "sea titan" } }, // electricity { // weak { "lesser lightning elemental", "lightning ball", "storm cloud", "lightning imp", "crackling mephit", "crackling orb", "storm mephit", "storm eagle", "storm sentinel", "greater lightning elemental" }, // normal { "spark", "shocker lizard", "thunder hawk", "electric eel", "lightning demon", "shocker imp", "shocking salamander", "thunderbolt", "storm giant", "storm giant shaman" }, // buff { "static ball", "lightning serpent", "lightning devil", "thundercloud", "thunder cat", "lightning djinn", "crackling roc", "young blue dragon", "blue dragon", "venerable blue dragon" } }, // cold { // weak { "lesser ice elemental", "snow storm", "polar bear cub", "frost revenant", "swirling blizzard", "frozen beast", "snow witch", "crystalline golem", "ice troll", "greater ice elemental" }, // normal { "ice rat", "snowman", "snow eagle", "winter mephit", "ice elemental", "glacier wolf", "frozen guardian", "white remorhaz", "frost giant shaman", "frost giant lord" }, // buff { "winter fox", "winter wolf cub", "ice mephit", "polar bear", "frozen yeti", "winter wolf", "abominable snowman", "young white dragon", "white dragon", "venerable white dragon" } } }; char bardConjureTitles[][10][35] = { { "dancing bunny rabbit", "ebony squirrel", "bearded lady", "blue chimpanzee", "singing sword", "redskin wild-elf", "mechanical dwarf", "psychotic animated cello", "clockwork wyrm", "untuned rabid barisax" }, { "talking sewer rat", "alley cat", "chattering tea pot", "ivory jaguar", "invisible entity", "singing velociraptor", "cackling scarecrow", "shade", "miming storm giant", "googleplex" }, { "angry teddy bear", "red spider monkey", "wild-eyed poet", "psychotic hand puppet", "schizophrenic serial killer clown", "sabre-tooth gnome", "albino dark-elf", "headless horseman", "rampaging bass drum", "vorpal bunny" } }; char mageConjureTitles[][10][35] = { { "large crow", "unseen servant", "jade rat", "guardian daemon", "marble owl", "chasme demon", "bone devil", "balor", "devil princess", "daemon overlord" }, { "large black beetle", "raven", "ebony cat", "quasit", "iron cobra", "shadow daemon", "succubus", "large blue demon", "ultradaemon", "hellfire darklord" }, { "white shrew", "red-blue tarantula", "azurite hawk", "fiendish imp", "pseudo dragon", "styx devil", "glabrezu demon", "pit fiend", "demon prince", "abyssal lord" } }; bool isTitle(bstring str) { std::map<int, PlayerTitle*>::iterator tt; std::map<bstring, PlayerClass*>::iterator cIt; PlayerClass* pClass=0; PlayerTitle* title=0; for(cIt = gConfig->classes.begin() ; cIt != gConfig->classes.end() ; cIt++) { pClass = (*cIt).second; for(tt = pClass->titles.begin() ; tt != pClass->titles.end(); tt++) { title = (*tt).second; if(str == title->getTitle(true) || str == title->getTitle(false)) return(true); } } std::map<int, DeityData*>::iterator it; DeityData* data=0; for(it = gConfig->deities.begin() ; it != gConfig->deities.end() ; it++) { data = (*it).second; for(tt = data->titles.begin() ; tt != data->titles.end(); tt++) { title = (*tt).second; if(str == title->getTitle(true) || str == title->getTitle(false)) return(true); } } return(false); } bool isClass(char str[80]) { for(int i=1; i<CLASS_COUNT; i++) { if(!strcmp(class_str[i], str) || !strcmp(class_abbrev[i], str)) return(true); } return(false); } //********************************************************************* // getAge //********************************************************************* int Player::getAge() const { const Calendar* calendar = gConfig->getCalendar(); int age=0; if(birthday) { age = calendar->getCurYear() - birthday->getYear(); if(calendar->getCurMonth() < birthday->getMonth()) age--; if(calendar->getCurMonth() == birthday->getMonth() && calendar->getCurDay() < birthday->getDay()) age--; } return(age); }