/* * login.cpp * Functions to log a person into the mud or create a new character * ____ _ * | _ \ ___ __ _| |_ __ ___ ___ * | |_) / _ \/ _` | | '_ ` _ \/ __| * | _ < __/ (_| | | | | | | \__ \ * |_| \_\___|\__,_|_|_| |_| |_|___/ * * 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-2009 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 "login.h" #include "commands.h" #include "guilds.h" #include "skills.h" #include "calendar.h" #include "magic.h" #include <sstream> #include <iomanip> #include <locale> //#include <arpa/telnet.h> /* * Generic get function, copy for future use * bool Create::get(Socket* sock, char* str, int mode) { if(mode == Create::doPrint) { } else if(mode == Create::doWork) { } return(true); } * */ //********************************************************************* // cmdReconnect //********************************************************************* int cmdReconnect(Player* player, cmd* cmnd) { Socket* sock = player->getSock(); player->print("\n\nReconnecting.\n\n\n"); player->save(true); gServer->clearPlayer(player->name); player->uninit(); free_crt(player); player = 0; sock->setPlayer(0); sock->reconnect(); return(0); } //********************************************************************* // login //********************************************************************* // This function is the first function that gets input from a player when // they log in. It asks for the player's name and password, and performs // the according function calls. void login(Socket* sock, char *str) { char tempstr[20]; Player *player=0; int newline=0; if(!sock) { printf("**** ERORR: Null socket in login.\n"); return; } if(sock->color == WANTS_MIRC_COLOR) newline = 1; switch(sock->getState()) { case LOGIN_DNS_LOOKUP: sock->print("Still performing DNS lookup, please be patient!\n"); return; case LOGIN_GET_COLOR: sock->color = WANTS_NO_COLOR; switch (low(str[0])) { case 'a': sock->color = WANTS_ANSI_COLOR; sock->printColor("^WANSI Color^x activated.\n"); break; case 'm': sock->color = WANTS_MIRC_COLOR; newline = 1; sock->printColor("^WmIRC Color^x activated. (For best results set background color to black)\n"); break; case 'x': sock->color = WANTS_MXP_COLOR; sock->printColor("^WANSI Color^x with ^WMXP^x activated.\n"); break; default: sock->print("\n"); break; } sock->askFor("Please enter name: "); if(newline) sock->print("\n"); gServer->processOutput(); sock->setState(LOGIN_GET_NAME); return; // End LOGIN_GET_COLOR case LOGIN_GET_LOCKOUT_PASSWORD: if(strcmp(sock->tempstr[0], str)) { sock->disconnect(); return; } sock->print("\n\nChoose - [A]nsi color, [M]irc color, [X] MXP + Ansi, or [N]o color\n: "); sock->setState(LOGIN_GET_COLOR); return; // End LOGIN_GET_LOCKOUT_PASSWORD case LOGIN_GET_NAME: lowercize(str, 1); if(strlen(str) >= 25) str[25]=0; if(!nameIsAllowed(str, sock)) { sock->askFor("Please enter name: "); if(newline) sock->print("\n"); return; } if(!loadPlayer(str, &player)) { strcpy(sock->tempstr[0], str); sock->print("\n%s? Did I get that right? ", str); if(newline) sock->print("\n"); sock->setState(LOGIN_CHECK_CREATE_NEW); return; } else { player->fd = -1; //gServer->addPlayer(player); sock->setPlayer(player); sock->print("%c%c%c", 255, 251, 1); sock->askFor("Please enter password: ");//, 255, 251, 1); if(newline) sock->print("\n"); sock->setState(LOGIN_GET_PASSWORD); return; } // End LOGIN_GET_NAME case LOGIN_CHECK_CREATE_NEW: if(str[0] != 'y' && str[0] != 'Y') { sock->tempstr[0][0] = 0; sock->askFor("Please enter name: "); if(newline) sock->print("\n"); sock->setState(LOGIN_GET_NAME); return; } else { sock->print("\nHit return: "); if(newline) sock->print("\n"); sock->setState(CREATE_NEW); return; } // End LOGIN_CHECK_CREATE_NEW case LOGIN_GET_PASSWORD: if(!sock->getPlayer()->isPassword(str)) { sock->write("\255\252\1\n\rIncorrect.\n\r"); if(newline) sock->print("\n"); logn("log.incorrect", "Invalid password(%s) for %s from %s\n", str, sock->getPlayer()->name, sock->getHostname().c_str()); sock->disconnect(); return; } else { sock->print("%c%c%c\n\r", 255, 252, 1); strcpy(tempstr, sock->getPlayer()->name); gServer->checkDuplicateName(sock, true); if(gServer->checkDouble(sock)) { gServer->cleanUp(); return; } gServer->cleanUp(); if(!loadPlayer(tempstr, &player)) { sock->askFor("Player no longer exists!\n\nPlease enter name: "); if(newline) sock->print("\n"); sock->setState(LOGIN_GET_NAME); return; } // if(player->flagIsSet(P_HARDCORE)) { // const StartLoc *location = gConfig->getStartLoc("highport"); // player->bind(location); // // put them in the docks: hp.100 // player->room.area = "hp"; // player->room.id = 100; // // remove all their stuff // player->coins.zero(); // otag *obj=0, *op = player->first_obj; // while(op) { // obj = op; // op = op->next_tag; // delete obj->obj; // delete obj; // } // player->first_obj = 0; // } sock->setPlayer(player); player->fd = sock->getFd(); player->setSock(sock); player->init(); gServer->addPlayer(player); // mIRC wants ANSI, but ANSI doesn't want mIRC if(sock->color == 1) { player->clearFlag(P_MIRC); player->setFlag(P_ANSI_COLOR); } else if(sock->color == 2) { player->setFlag(P_ANSI_COLOR); player->setFlag(P_MIRC); } sock->setState(CON_PLAYING); // if(player->flagIsSet(P_HARDCORE)) { // player->clearFlag(P_HARDCORE); // player->print("\n\n\n"); // player->print("You wake up on the shores of Derlith, completely naked...\n"); // player->print("\n\n"); // player->print("You do not know how long you have been unconscious, or how long you have\n"); // player->print("been floating at sea. The sounds of the ocean fill the air, interrupted by\n"); // player->print("the bustling noise of a city street. An occasional bell rings and the\n"); // player->print("sounds of horse-drawn carriages stumbling over cobblestone soon grow louder\n"); // player->print("and louder. You look around to find yourself at the docks of Highport.\n"); // player->print("People stare at you as they pass.\n"); // player->print("\n\n"); // player->print("You no longer feel hunted, as you did in Oceancrest. You feel the peaceful\n"); // player->print("onset of immortality that comes with living in Derlith. You are now free to\n"); // player->print("continue your adventures in this world...\n"); // player->print("\n\n\n"); // } } } } // Blah I know its a big hack...fix it later if you don't like it int setPlyClass(Socket* sock, int cClass) { // Make sure they both start off at 0 sock->getPlayer()->setClass(0); sock->getPlayer()->setSecondClass(0); // Define's BASE as first # to interpret as multi class // Increment this when a class is added switch(cClass) { case ASSASSIN: case BARD: case BERSERKER: case CLERIC: case DEATHKNIGHT: case DRUID: case FIGHTER: case LICH: case MAGE: case MONK: case PALADIN: case RANGER: case ROGUE: case THIEF: case VAMPIRE: case WEREWOLF: sock->getPlayer()->setClass(cClass); break; case MULTI_BASE + 0: sock->getPlayer()->setClass(FIGHTER); sock->getPlayer()->setSecondClass(MAGE); break; case MULTI_BASE + 1: sock->getPlayer()->setClass(FIGHTER); sock->getPlayer()->setSecondClass(THIEF); break; case MULTI_BASE + 2: sock->getPlayer()->setClass(CLERIC); sock->getPlayer()->setSecondClass(ASSASSIN); break; case MULTI_BASE + 3: sock->getPlayer()->setClass(MAGE); sock->getPlayer()->setSecondClass(THIEF); break; case MULTI_BASE + 4: sock->getPlayer()->setClass(THIEF); sock->getPlayer()->setSecondClass(MAGE); break; case MULTI_BASE + 5: sock->getPlayer()->setClass(CLERIC); sock->getPlayer()->setSecondClass(FIGHTER); break; case MULTI_BASE + 6: sock->getPlayer()->setClass(MAGE); sock->getPlayer()->setSecondClass(ASSASSIN); break; default: break; } return(0); } //********************************************************************* // setPlyDeity //********************************************************************* void setPlyDeity(Socket* sock, int deity) { switch(deity) { case ARAMON: case CERIS: case ENOCH: case GRADIUS: case ARES: case KAMIRA: case LINOTHAN: case ARACHNUS: break; default: deity = 0; break; } sock->getPlayer()->setDeity(deity); } //********************************************************************* // createPlayer //********************************************************************* // This function allows a new player to create their character. void createPlayer(Socket* sock, char *str) { switch(sock->getState()) { case CREATE_NEW: { Player* target = sock->getPlayer(); sock->print("\n"); if(target) { gServer->clearPlayer(target->name); delete target; } target = new Player; if(!target) merror("createPlayer", FATAL); target->fd = -1; target->setSock(sock); sock->setPlayer(target); target->defineColors(); } if(isdm(sock->tempstr[0])) { sock->print("\nYou must enter a password to create that character.\n"); sock->print("Please enter password: "); Create::newline(sock); gServer->processOutput(); sock->setState(CREATE_GET_DM_PASSWORD); return; } else goto no_pass; // End CREATE_NEW case CREATE_GET_DM_PASSWORD: if(strcmp(gConfig->getDmPass().c_str(), str)) { sock->disconnect(); return; } case CREATE_CHECK_LOCKED_OUT: no_pass: if(gConfig->isLockedOut(sock) == 1) { sock->disconnect(); return; } Create::getRace(sock, str, Create::doPrint); return; case CREATE_GET_RACE: if(!Create::getRace(sock, str, Create::doWork)) return; if( gConfig->getRace(sock->getPlayer()->getRace())->isParent() && Create::getSubRace(sock, str, Create::doPrint) ) return; Create::getSex(sock, str, Create::doPrint); return; case CREATE_GET_SUBRACE: if(!Create::getSubRace(sock, str, Create::doWork)) return; Create::getClass(sock, str, Create::doPrint); return; case CREATE_GET_SEX: if(!Create::getSex(sock, str, Create::doWork)) return; Create::getClass(sock, str, Create::doPrint); return; case CREATE_GET_CLASS: if(!Create::getClass(sock, str, Create::doWork)) return; if(gConfig->classes[get_class_string(sock->getPlayer()->getClass())]->needsDeity()) Create::getDeity(sock, str, Create::doPrint); else if(Create::getLocation(sock, str, Create::doPrint)) Create::getStats(sock, str, Create::doPrint); return; case CREATE_GET_DEITY: if(!Create::getDeity(sock, str, Create::doWork)) return; if(Create::getLocation(sock, str, Create::doPrint)) Create::getStats(sock, str, Create::doPrint); return; case CREATE_START_LOC: if(!Create::getLocation(sock, str, Create::doWork)) return; Create::getStats(sock, str, Create::doPrint); return; case CREATE_GET_STATS: if(!Create::getStats(sock, str, Create::doWork)) return; if(gConfig->getRace(sock->getPlayer()->getRace())->bonusStat()) Create::getBonusStat(sock, str, Create::doPrint); else { Create::finishStats(sock); Create::startCustom(sock, str, Create::doPrint); } return; case CREATE_BONUS_STAT: if(!Create::getBonusStat(sock, str, Create::doWork)) return; Create::getPenaltyStat(sock, str, Create::doPrint); return; case CREATE_PENALTY_STAT: if(!Create::getPenaltyStat(sock, str, Create::doWork)) return; Create::startCustom(sock, str, Create::doPrint); return; case CREATE_START_CUSTOM: if(Create::startCustom(sock, str, Create::doWork)) Create::getCommunity(sock, str, Create::doPrint); else Create::getProf(sock, str, Create::doPrint); return; case CREATE_GET_PROF: if(!Create::getProf(sock, str, Create::doWork)) return; if(gConfig->classes[get_class_string(sock->getPlayer()->getClass())]->numProfs()==2) Create::getSecondProf(sock, str, Create::doPrint); else Create::getPassword(sock, str, Create::doPrint); return; case CREATE_SECOND_PROF: if(!Create::getSecondProf(sock, str, Create::doWork)) return; Create::getPassword(sock, str, Create::doPrint); return; case CREATE_GET_PASSWORD: if(!Create::getPassword(sock, str, Create::doWork)) return; Create::done(sock, str, Create::doPrint); return; case CREATE_DONE: Create::done(sock, str, Create::doWork); return; // handle character customization here: case CUSTOM_COMMUNITY: if(!Create::getCommunity(sock, str, Create::doWork)) return; Create::getFamily(sock, str, Create::doPrint); return; case CUSTOM_FAMILY: if(!Create::getFamily(sock, str, Create::doWork)) return; Create::getSocial(sock, str, Create::doPrint); return; case CUSTOM_SOCIAL: if(!Create::getSocial(sock, str, Create::doWork)) return; Create::getEducation(sock, str, Create::doPrint); return; case CUSTOM_EDUCATION: if(!Create::getEducation(sock, str, Create::doWork)) return; Create::getHeight(sock, str, Create::doPrint); return; case CUSTOM_HEIGHT: if(!Create::getHeight(sock, str, Create::doWork)) return; Create::getWeight(sock, str, Create::doPrint); return; case CUSTOM_WEIGHT: if(!Create::getWeight(sock, str, Create::doWork)) return; Create::getStats(sock, str, Create::doPrint); return; } } // // newline function so I don't have to copy this everywhere // void Create::newline(Socket* sock) { if(sock->color == WANTS_MIRC_COLOR) sock->print("\n"); } //********************************************************************* // addStartingItem //********************************************************************* void Create::addStartingItem(Player* player, bstring area, int id, bool wear, bool skipUseCheck) { CatRef cr; cr.setArea(area); cr.id = id; Object* object=0; if(loadObject(cr, &object)) { object->setFlag(O_STARTING); // if they can't use it, dont even give it to them if(!skipUseCheck && !player->canUse(object, true)) { delete object; } else { player->addObj(object); if(wear) player->equip(object, false); } } } //********************************************************************* // addStartingWeapon //********************************************************************* void Create::addStartingWeapon(Player* player, bstring weapon) { if(weapon == "sword") Create::addStartingItem(player, "tut", 28); else if(weapon == "great-sword") Create::addStartingItem(player, "tut", 21); else if(weapon == "polearm") Create::addStartingItem(player, "tut", 24); else if(weapon == "whip") Create::addStartingItem(player, "tut", 29); else if(weapon == "rapier") Create::addStartingItem(player, "tut", 25); else if(weapon == "spear") Create::addStartingItem(player, "tut", 26); else if(weapon == "axe") Create::addStartingItem(player, "tut", 14); else if(weapon == "great-axe") Create::addStartingItem(player, "tut", 18); else if(weapon == "dagger") Create::addStartingItem(player, "tut", 17); else if(weapon == "staff") Create::addStartingItem(player, "tut", 27); else if(weapon == "mace") Create::addStartingItem(player, "tut", 23); else if(weapon == "great-mace") Create::addStartingItem(player, "tut", 20); else if(weapon == "club") Create::addStartingItem(player, "tut", 16); else if(weapon == "hammer") Create::addStartingItem(player, "tut", 22); else if(weapon == "great-hammer") Create::addStartingItem(player, "tut", 19); else if(weapon == "bow") Create::addStartingItem(player, "tut", 15); else if(weapon == "crossbow") Create::addStartingItem(player, "tut", 30); else if(weapon == "thrown") Create::addStartingItem(player, "tut", 31); } // // work functions // //********************************************************************* // getSex //********************************************************************* bool Create::getSex(Socket* sock, char* str, int mode) { const RaceData* rdata = gConfig->getRace(sock->getPlayer()->getRace()); if(!rdata->isGendered()) { sock->getPlayer()->setSex(SEX_NONE); return(true); } if(mode == Create::doPrint) { sock->askFor("Do you wish to be [^WM^x] Male or [^WF^x] Female? "); Create::newline(sock); sock->setState(CREATE_GET_SEX); } else if(mode == Create::doWork) { if(low(str[0]) == 'f') { sock->getPlayer()->setSex(SEX_FEMALE); sock->printColor("You are now ^Wfemale^x.\n"); } else if(low(str[0]) == 'm') { sock->getPlayer()->setSex(SEX_MALE); sock->printColor("You are now ^Wmale^x.\n"); } else { sock->askFor("[^WM^x] Male or [^WF^x] Female: "); Create::newline(sock); sock->setState(CREATE_GET_SEX); return(false); } } return(true); } //********************************************************************* // getRace //********************************************************************* #define FBUF 800 bool Create::getRace(Socket* sock, char* str, int mode) { std::map<int, RaceData*> choices; std::map<int, RaceData*>::iterator it; int k=0; // figure out what they can play for(it = gConfig->races.begin() ; it != gConfig->races.end() ; it++) { // if not playable, skip // if sub race, skip, they'll choose when they pick parent race if((*it).second->isPlayable() && !(*it).second->getParentRace()) choices[k++] = (*it).second; } if(mode == Create::doPrint) { char file[80]; int ff=0; // show them the race menu header sprintf(file, "%s/race_menu.0.txt", CONFPATH); viewLoginFile(sock, file); // show them the main race menu sprintf(file, "%s/race_menu.1.txt", CONFPATH); char buf[FBUF + 1]; ff = open(file, O_RDONLY, 0); k=0; if(ff < 0) { // we can't load the file? just give them a menu for(it = choices.begin() ; it != choices.end() ; it++) { sock->printColor("[^W%1c^x] %-16s\n", k + 65, (*it).second->getName().c_str()); k++; } return(0); } else { // display them the file int i, l, n, line; long offset; zero(buf, sizeof(buf)); while(1) { n = read(ff, buf, FBUF); l = 0; for(i=0; i<n; i++) { if(buf[i] == '\n') { buf[i] = 0; if(i != 0 && buf[i-1] == '\r') buf[i-1] = 0; line++; sock->printColor("%s", &buf[l]); // print out the next playable race if(choices.find(k) != choices.end()) { sock->printColor("[^W%1c^x] %-16s", k + 65, choices[k]->getName().c_str()); k++; } sock->print("\n"); offset += (i - l + 1); l = i + 1; } } if(l != n) { sock->printColor("%s", &buf[l]); offset += (i - l); } if(n < FBUF) { close(ff); break; } } } sock->print("\n\n\n"); sock->askFor("Choose one: "); Create::newline(sock); sock->setState(CREATE_GET_RACE); } else if(mode == Create::doWork) { k = low(str[0]) - 'a'; if(choices.find(k) != choices.end()) { sock->getPlayer()->setRace(choices[k]->getId()); } else { sock->print("\nChoose one: "); Create::newline(sock); sock->setState(CREATE_GET_RACE); return(false); } if(!sock->getPlayer()->getRace()) return(false); if(!gConfig->getRace(sock->getPlayer()->getRace())->isParent()) Create::finishRace(sock); } return(true); } //********************************************************************* // getSubRace //********************************************************************* bool Create::getSubRace(Socket* sock, char* str, int mode) { std::map<int, RaceData*> choices; std::map<int, RaceData*>::iterator it; int k=0; // figure out what they can play for(it = gConfig->races.begin() ; it != gConfig->races.end() ; it++) { if( (*it).second->isPlayable() && ( (*it).second->getId() == sock->getPlayer()->getRace() || (*it).second->getParentRace() == sock->getPlayer()->getRace() ) ) choices[k++] = (*it).second; } k=0; if(mode == Create::doPrint) { std::ostringstream oStr; char c; bool hasChildren = false; // set left aligned oStr.setf(std::ios::left, std::ios::adjustfield); oStr.imbue(std::locale("")); oStr << "\nChoose a sub race:\n"; for(it = choices.begin() ; it != choices.end() ; it++) { // self doesn't count when counting children if((*it).second->getId() != sock->getPlayer()->getRace()) hasChildren = true; if(k%2==0) oStr << "\n" << std::setw(20) << " "; c = ++k + 64; oStr << "[^W" << c << "^x] " << std::setw(16) << (*it).second->getName(); } // if there's no children, none of the subraces are playable, // so they have to choose the parent if(!hasChildren) { Create::finishRace(sock); return(false); } sock->printColor("%s\n\n", oStr.str().c_str()); sock->askFor("Choose one: "); Create::newline(sock); sock->setState(CREATE_GET_SUBRACE); } else if(mode == Create::doWork) { k = low(str[0]) - 'a'; if(choices.find(k) != choices.end()) { sock->getPlayer()->setRace(choices[k]->getId()); Create::finishRace(sock); return(true); } return(false); } return(true); } //********************************************************************* // finishRace //********************************************************************* void Create::finishRace(Socket* sock) { const RaceData* race = gConfig->getRace(sock->getPlayer()->getRace()); sock->printColor("\nYour chosen race: ^W%s^x\n\n", race->getName().c_str()); sock->getPlayer()->setSize(race->getSize()); sock->getPlayer()->initLanguages(); std::list<bstring>::const_iterator it; for(it = race->effects.begin() ; it != race->effects.end() ; it++) { sock->getPlayer()->addPermEffect((*it)); } } //********************************************************************* // getClass //********************************************************************* bool Create::getClass(Socket* sock, char* str, int mode) { int l=0, k=0; if(mode == Create::doPrint) { sock->print(" ____________\n"); sock->print(" /------------\\ VVVVVVVVVVVVVVVV\n"); sock->print(" // ___ ___ \\\\ %12s: Choose A Class\n", gConfig->getRace(sock->getPlayer()->getRace())->getName().c_str()); sock->print(" \\_/ \\ / \\_/ ^^^^^^^^^^^^^^^^\n"); sock->print(" ______/ \\__________________________________________________\n"); sock->print("<______ ________\\\\\\\\_____\\\\\\\\_____\\\\\\\\_____\\\\\\\\_____\\\\\\\\__]\n"); sock->print(" _ \\ / _\n"); sock->print(" / \\___/ \\___/ \\\n"); sock->print(" \\\\____________//\n"); sock->print(" `------------'"," "); for(l=1, k=0; l<CLASS_COUNT_MULT; l++) { if(gConfig->getRace(sock->getPlayer()->getRace())->allowedClass(l)) { if(k%2==0) sock->print("\n%20s", " "); sock->printColor("[^W%1c^x] %-16s", ++k + 64, allowedClassesStr[l-1]); } } sock->print("\n |\\\n"); sock->print(" <<\\ _\n"); sock->print(" / \\ //\n"); sock->print(" .--------------------------------------------------------{o}______/|\n"); sock->print("< -===========================================:::{*}///////////]\n"); sock->print(" `--------------------------------------------------------{o}~~~~~~\\|\n"); sock->print(" \\ / \\\\\n"); sock->print(" <</ -\n"); sock->print(" |/\n"); sock->askFor("Choose one: "); Create::newline(sock); sock->setState(CREATE_GET_CLASS); } else if(mode == Create::doWork) { int i=0; if(!isalpha(str[0])) i = -1; else i = (int)(up(str[0]) - 64); for(l=1, k=0; l<CLASS_COUNT_MULT; l++) { if(gConfig->getRace(sock->getPlayer()->getRace())->allowedClass(l)) { k++; if(k == i) setPlyClass(sock, l); } } if(sock->getPlayer()->getClass()) { if(sock->getPlayer()->getSecondClass()) sock->printColor("Your chosen class: ^W%s/%s\n", get_class_string(sock->getPlayer()->getClass()), get_class_string(sock->getPlayer()->getSecondClass())); else sock->printColor("Your chosen class: ^W%s\n", get_class_string(sock->getPlayer()->getClass())); } if(!sock->getPlayer()->getClass()) { sock->printColor("Invalid selection: ^W%s\n", str); sock->askFor("Choose one: "); Create::newline(sock); sock->setState(CREATE_GET_CLASS); return(false); } } return(true); } //********************************************************************* // getDeity //********************************************************************* bool Create::getDeity(Socket* sock, char* str, int mode) { int l=0, k=0; const RaceData* race = gConfig->getRace(sock->getPlayer()->getRace()); if(mode == Create::doPrint) { sock->print("Please choose a deity:\n"); for(l=1, k=0 ; l<DEITY_COUNT ; l++) { if(race->allowedDeity(sock->getPlayer()->getClass(), sock->getPlayer()->getSecondClass(), l)) { if(k%2==0) sock->print("\n%20s", " "); sock->printColor("[^W%1c^x] %-16s", ++k + 64, gConfig->getDeity(l)->getName().c_str()); } } sock->askFor("\n\nChoose one: "); Create::newline(sock); sock->setState(CREATE_GET_DEITY); } else if(mode == Create::doWork) { int i=0; if(!isalpha(str[0])) i = -1; else i = (int)(up(str[0]) - 64); for(l=1, k=0; l < CLASS_COUNT+4; l++) { if(race->allowedDeity(sock->getPlayer()->getClass(), sock->getPlayer()->getSecondClass(), l)) { k++; if(k == i) setPlyDeity(sock, l); } } if(sock->getPlayer()->getDeity()) sock->printColor("Your chosen deity: ^W%s\n", gConfig->getDeity(sock->getPlayer()->getDeity())->getName().c_str()); else { sock->printColor("Invalid selection: ^W%s\n", str); sock->askFor("Choose one: "); Create::newline(sock); sock->setState(CREATE_GET_DEITY); return(false); } } return(true); } //********************************************************************* // getLocation //********************************************************************* // from start.cpp bool startingChoices(Player* player, char* str, char* location, bool choose); bool Create::getLocation(Socket* sock, char* str, int mode) { char location[256]; if(mode == Create::doPrint) { if(!startingChoices(sock->getPlayer(), str, location, false)) { sock->print("\n\nPlease choose a starting location:"); sock->printColor("\n %s\n\n", location); // TODO: Dom: HC //sock->printColor("^YCaution:^x If you choose Oceancrest as a starting location, you will\n"); //sock->printColor("automatically be entered into the tournament. See the forum for details.\n"); //sock->printColor("^Yhttp://forums.rohonline.net/topic/1655/\n\n"); sock->askFor(": "); Create::newline(sock); sock->setState(CREATE_START_LOC); return(false); } } else if(mode == Create::doWork) { if(!startingChoices(sock->getPlayer(), str, location, true)) { sock->print("Invalid selection.\n"); sock->askFor(": "); Create::newline(sock); sock->setState(CREATE_START_LOC); return(false); } } sock->print("\n\nYour starting location is: "); sock->print("\n %s\n\n", location); return(true); } //********************************************************************* // startCustom //********************************************************************* bool Create::startCustom(Socket* sock, char* str, int mode) { // still in progress! bypass for now return(getProf(sock, str, mode)); if(mode == Create::doPrint) { sock->printColor("\nFor more customization options, press [^WM^x].\n"); sock->print("To continue with your character, press enter.\n"); sock->askFor(": "); Create::newline(sock); sock->setState(CREATE_START_CUSTOM); } else if(mode == Create::doWork) { if(str[0] != 'm' && str[0] != 'M') { // randomly customize them return(false); } } return(true); } //********************************************************************* // getStats //********************************************************************* bool Create::getStats(Socket* sock, char* str, int mode) { if(mode == Create::doPrint) { sock->print("\nYou have 56 points to distribute among your 5 stats. Please enter your 5"); sock->print("\nnumbers in the following order: Strength, Dexterity, Constitution,"); sock->print("\nIntelligence, Piety. No stat may be smaller than 3 or larger than 18."); sock->print("\nUse the following format: ## ## ## ## ##\n\n"); sock->askFor(": "); Create::newline(sock); sock->setState(CREATE_GET_STATS); } else if(mode == Create::doWork) { int i=0, l=0, k=0, sum=0, num[5], n = strlen(str); for(i=0; i<=n; i++) { if(str[i]==' ' || str[i]==0) { str[i] = 0; num[k++] = atoi(&str[l]); l = i+1; } if(k>4) break; } if(k<5) { sock->print("Please enter all 5 numbers.\n"); sock->askFor(": "); Create::newline(sock); sock->setState(CREATE_GET_STATS); return(false); } for(i=0; i<5; i++) { if(num[i] < 3 || num[i] > 18) { sock->print("No stats < 3 or > 18 please.\n"); sock->print(": "); Create::newline(sock); sock->setState(CREATE_GET_STATS); return(false); } sum += num[i]; } if(sum != 56) { sock->print("Stat total must equal 56 points.\n"); sock->print(": "); Create::newline(sock); sock->setState(CREATE_GET_STATS); return(false); } sock->getPlayer()->strength.setMax(num[0] * 10); sock->getPlayer()->dexterity.setMax(num[1] * 10); sock->getPlayer()->constitution.setMax(num[2] * 10); sock->getPlayer()->intelligence.setMax(num[3] * 10); sock->getPlayer()->piety.setMax(num[4] * 10); } return(true); } //********************************************************************* // finishStats //********************************************************************* void Create::finishStats(Socket* sock) { Player* ply = sock->getPlayer(); ply->strength.addMax(gConfig->getRace(ply->getRace())->getStatAdj(STR)); ply->dexterity.addMax(gConfig->getRace(ply->getRace())->getStatAdj(DEX)); ply->constitution.addMax(gConfig->getRace(ply->getRace())->getStatAdj(CON)); ply->intelligence.addMax(gConfig->getRace(ply->getRace())->getStatAdj(INT)); ply->piety.addMax(gConfig->getRace(ply->getRace())->getStatAdj(PTY)); ply->strength.setMax(MAX(10, ply->strength.getMax())); ply->dexterity.setMax(MAX(10, ply->dexterity.getMax())); ply->constitution.setMax(MAX(10, ply->constitution.getMax())); ply->intelligence.setMax(MAX(10, ply->intelligence.getMax())); ply->piety.setMax(MAX(10, ply->piety.getMax())); sock->print("Your stats: %d %d %d %d %d\n", ply->strength.getMax(), ply->dexterity.getMax(), ply->constitution.getMax(), ply->intelligence.getMax(), ply->piety.getMax()); } //********************************************************************* // getBonusStat //********************************************************************* bool Create::getBonusStat(Socket* sock, char* str, int mode) { if(mode == Create::doPrint) { sock->print("\nRaise which stat?\n[A] Strength, [B] Dexterity, [C] Constitution, [D] Intelligence, or [E] Piety.\n : "); Create::newline(sock); sock->setState(CREATE_BONUS_STAT); } else if(mode == Create::doWork) { switch(low(str[0])) { case 'a': sock->getPlayer()->strength.addMax(10); break; case 'b': sock->getPlayer()->dexterity.addMax(10); break; case 'c': sock->getPlayer()->constitution.addMax(10); break; case 'd': sock->getPlayer()->intelligence.addMax(10); break; case 'e': sock->getPlayer()->piety.addMax(10); break; default: sock->print("\nChoose one: "); Create::newline(sock); sock->setState(CREATE_BONUS_STAT); return(false); } } return(true); } //********************************************************************* // getPenaltyStat //********************************************************************* bool Create::getPenaltyStat(Socket* sock, char* str, int mode) { if(mode == Create::doPrint) { sock->printColor("\nChoose your stat to lower:\n[^WA^x] Strength, [^WB^x] Dexterity, [^WC^x] Constitution, [^WD^x] Intelligence, or [^WE^x] Piety.\n : "); Create::newline(sock); sock->setState(CREATE_PENALTY_STAT); } else if(mode == Create::doWork) { switch(low(str[0])) { case 'a': sock->getPlayer()->strength.addMax(-10); break; case 'b': sock->getPlayer()->dexterity.addMax(-10); break; case 'c': sock->getPlayer()->constitution.addMax(-10); break; case 'd': sock->getPlayer()->intelligence.addMax(-10); break; case 'e': sock->getPlayer()->piety.addMax(-10); break; default: sock->print("\nChoose one: "); Create::newline(sock); sock->setState(CREATE_PENALTY_STAT); return(false); } } return(true); } //********************************************************************* // handleWeapon //********************************************************************* bool Create::handleWeapon(Socket* sock, int mode, char ch) { int i=0; if(!isalpha(ch)) i = -1; else i = (int)(up(ch) - 64); if(mode == Create::doPrint) { if(sock->getPlayer()->getClass() == WEREWOLF) { sock->printColor("\n\n^WSlashing Weapons^x\n [^WA^x] Claws\n"); return(true); } else if(sock->getPlayer()->getClass() == MONK) { sock->printColor("\n\n^WCrushing Weapons^x\n [^WA^x] Bare-Handed\n"); return(true); } } else { if(sock->getPlayer()->getClass() == WEREWOLF && low(ch) == 'a') { sock->getPlayer()->setSkill("claw", 1); return(true); } else if(sock->getPlayer()->getClass() == MONK && low(ch) == 'a') { sock->getPlayer()->setSkill("bare-hand", 1); return(true); } else if(sock->getPlayer()->getClass() == MONK || sock->getPlayer()->getClass() == WEREWOLF) { sock->print("Choose a weapon skill:\n"); sock->setState(CREATE_GET_PROF); return(false); } } if(!sock->getPlayer()->knowsSkill("bare-hand")) sock->getPlayer()->addSkill("bare-hand", 1); std::map<bstring, bstring>::const_iterator sgIt; std::map<bstring, Skill*>::const_iterator sIt; int k = 0, n = 0; bstring curGroup, curGroupDisplay; Skill* curSkill; for(sgIt = gConfig->skillGroups.begin() ; sgIt != gConfig->skillGroups.end() ; sgIt++) { curGroup = (*sgIt).first; curGroupDisplay = (*sgIt).second; if(curGroup.left(7) != "weapons") continue; if(sock->getPlayer()->getClass() == CLERIC && sock->getPlayer()->getDeity() == CERIS) { if(curGroup.Find("slashing") != -1 || curGroup.Find("piercing") != -1) continue; } if(mode == Create::doPrint) { sock->printColor("^W\n\n%s", (*sgIt).second.c_str()); n = 0; } for(sIt = gConfig->skills.begin() ; sIt != gConfig->skills.end() ; sIt++) { curSkill = (*sIt).second; if(curSkill->getGroup() != curGroup) continue; if(curSkill->getName() == "claw") continue; if(sock->getPlayer()->getClass() == CLERIC && sock->getPlayer()->getDeity() == CERIS) if(curSkill->getName() == "whip") continue; if(sock->getPlayer()->knowsSkill(curSkill->getName())) continue; if(mode == Create::doPrint) { if(n++%2==0) sock->print("\n%5s", " "); sock->printColor("[^W%1c^x] %-30s", ++k + 64, curSkill->getDisplayName().c_str()); } else { if(i == ++k) { if(sock->getState() == CON_CHOSING_WEAPONS) sock->getPlayer()->setSkill(curSkill->getName(), MAX(1, (sock->getPlayer()->getLevel()-1)*10)); else sock->getPlayer()->setSkill(curSkill->getName(), 1); Create::addStartingWeapon(sock->getPlayer(), curSkill->getName()); sock->printColor("You have learned how to use ^W%s^x.\n", curSkill->getDisplayName().c_str()); return(true); } } } } if(mode == Create::doPrint) { if(k==0) return(false); else return(true); } return(false); } //********************************************************************* // cmdWeapons //********************************************************************* int cmdWeapons(Player* player, cmd* cmnd) { if(player->getWeaponTrains() < 1) { player->print("You don't have any weapon trains left!\n"); return(0); } // if(!player->getRoom()->findWeaponsTrainer()) { // player->print("You can't find anyone here to train you in weapon skills!\n"); // return(0); // } player->printColor("You have ^W%d^x weapon skills to choose.\n", player->getWeaponTrains()); if(!Create::handleWeapon(player->getSock(), Create::doPrint, '\0')) { player->print("\n\nSorry, couldn't find any weapon skills you don't know that you can learn.\n"); return(0); } player->getSock()->setState(CON_CHOSING_WEAPONS); player->getSock()->askFor("\n(0 to exit): "); return(0); } //********************************************************************* // convertNewWeaponSkills //********************************************************************* void convertNewWeaponSkills(Socket* sock, char *str) { if(!isalpha(str[0])) { sock->setState(CON_PLAYING); return; } if(Create::handleWeapon(sock, Create::doWork, str[0])) { sock->getPlayer()->subWeaponTrains(1); if(sock->getPlayer()->getWeaponTrains() == 0) { sock->print("Exiting weapon skill selector.\n"); sock->setState(CON_PLAYING); return; } else { sock->print("You have %d weapon skill(s) left to choose.", sock->getPlayer()->getWeaponTrains()); if(!Create::handleWeapon(sock, Create::doPrint, str[0])) { sock->print("\n\nSorry, couldn't find any weapon skills you don't know that you can learn.\n"); sock->setState(CON_PLAYING); return; } sock->askFor("\n(0 to exit): "); } } else { sock->print("Please pick: "); } } //********************************************************************* // getProf //********************************************************************* bool Create::getProf(Socket* sock, char* str, int mode) { if(mode == Create::doPrint) { if(gConfig->classes[get_class_string(sock->getPlayer()->getClass())]->numProfs() > 1) { sock->print("\nPick %d weapon skills:", gConfig->classes[get_class_string(sock->getPlayer()->getClass())]->numProfs()); } else { sock->print("\nChoose a weapon skill:"); } Create::handleWeapon(sock, mode, str[0]); sock->askFor("\n: "); Create::newline(sock); sock->setState(CREATE_GET_PROF); } else if(mode == Create::doWork) { if(Create::handleWeapon(sock, mode, str[0])) return(true); else { sock->print("Choose a weapon skill:\n"); sock->setState(CREATE_GET_PROF); return(false); } } return(true); } //********************************************************************* // getSecondProf //********************************************************************* bool Create::getSecondProf(Socket* sock, char* str, int mode) { if(mode == Create::doPrint) { Create::handleWeapon(sock, mode, str[0]); sock->print("\nPick a second proficiency:\n"); sock->askFor(": "); sock->setState(CREATE_SECOND_PROF); } else if(mode == Create::doWork) { if(Create::handleWeapon(sock, mode, str[0])) return(true); else { sock->print("Pick a second proficiency!\n"); sock->askFor(": "); sock->setState(CREATE_SECOND_PROF); return(false); } } return(true); } //********************************************************************* // getPassword //********************************************************************* bool Create::getPassword(Socket* sock, char* str, int mode) { if(mode == Create::doPrint) { sock->print("\nYou must now choose a password. Remember that it\n"); sock->print("is YOUR responsibility to remember this password. The staff\n"); sock->print("at Realms will not give out password information to anyone\n"); sock->print("at any time. Please write it down someplace, because if you\n"); sock->print("forget it, you will no longer be able to play this character.\n\n"); sock->print("Please choose a password (up to 14 chars): "); Create::newline(sock); sock->setState(CREATE_GET_PASSWORD); } else if(mode == Create::doWork) { if(!isValidPassword(sock, str)) { sock->print("\nChoose a password: "); Create::newline(sock); sock->setState(CREATE_GET_PASSWORD); return(false); } sock->getPlayer()->setFlag(P_PASSWORD_CURRENT); //t = time(0); //strcpy(sock->getPlayer()->last_mod, ctime(&t)); sock->getPlayer()->setPassword(str); } return(true); } //********************************************************************* // done //********************************************************************* void Create::done(Socket* sock, char* str, int mode) { if(mode == Create::doPrint) { char file[80]; sprintf(file, "%s/policy_login.txt", CONFPATH); viewLoginFile(sock, file); sock->print("[Press Enter to Continue]"); Create::newline(sock); sock->setState(CREATE_DONE); } else if(mode == Create::doWork) { Player* player = sock->getPlayer(); long t = time(0); int i=0; player->setBirthday(); player->setCreated(); strcpy(player->name, sock->tempstr[0]); if(gServer->checkDuplicateName(sock, false)) return; if(gServer->checkDouble(sock)) return; if(Player::exists(player->name)) { sock->printColor("\n\n^ySorry, that player already exists.^x\n\n\n"); sock->reconnect(); return; } player->lasttime[LT_AGE].interval = 0; t = time(0); for(i=0; i<MAX_LT; i++) player->lasttime[i].ltime = t; // Moved here so con affects a level 1's hp player->adjustStats(); player->upLevel(); player->addSkill("defense", 1); // Give out parry & block switch(player->getClass()) { // These classes get block + parry case ASSASSIN: case BARD: case FIGHTER: case RANGER: case ROGUE: case PALADIN: case DEATHKNIGHT: player->addSkill("block", 1); // fall through for parry case THIEF: player->addSkill("parry", 1); break; case BERSERKER: player->addSkill("block", 1); // Zerkers are more brute force than finnese...no parry break; default: break; } // Give out armor skills here switch(player->getClass()) { case BARD: case BERSERKER: case FIGHTER: case PALADIN: case DEATHKNIGHT: case RANGER: player->addSkill("plate", 1); player->addSkill("chain", 1); case ASSASSIN: case THIEF: case ROGUE: case VAMPIRE: case DRUID: case CLERIC: player->addSkill("leather", 1); case MAGE: case MONK: case LICH: case WEREWOLF: default: player->addSkill("cloth", 1); break; } // A few clerics get plate if(player->getClass() == CLERIC && !player->getSecondClass()) { if(player->getDeity() == ENOCH || player->getDeity() == ARES || player->getDeity() == GRADIUS) { player->addSkill("plate", 1); player->addSkill("chain", 1); } } // TODO: Dom: make this mage only if(player->getClass() != BERSERKER) { player->addSkill("abjuration", 1); player->addSkill("conjuration", 1); player->addSkill("divination", 1); player->addSkill("enchantment", 1); player->addSkill("evocation", 1); player->addSkill("illusion", 1); player->addSkill("necromancy", 1); player->addSkill("translocation", 1); player->addSkill("transmutation", 1); player->addSkill("fire", 1); player->addSkill("water", 1); player->addSkill("earth", 1); player->addSkill("air", 1); player->addSkill("cold", 1); player->addSkill("electric", 1); } if(player->getClass() == LICH) player->learnSpell(S_SAP_LIFE); Create::addStartingItem(player, "tut", 10, true); Create::addStartingItem(player, "tut", 11, true); Create::addStartingItem(player, "tut", 12, true); Create::addStartingItem(player, "tut", 13, true); player->fd = sock->getFd(); player->setSock(sock); sock->setPlayer(player); player->init(); sock->print("\n"); // player->adjustStats(); player->setFlag(P_NO_AUTO_ATTACK); player->setFlag(P_LAG_PROTECTION_SET); if(player->getClass() == BARD) player->learnSong(SONG_HEAL); player->save(true); gServer->addPlayer(player); sock->print("Type 'welcome' at prompt to get more info on the game\nand help you get started.\n"); sock->setState(CON_PLAYING); } } //********************************************************************* // adjustStats //********************************************************************* void Creature::adjustStats() { strength.restore(); dexterity.restore(); constitution.restore(); intelligence.restore(); piety.restore(); strength.setInitial(strength.getCur()); dexterity.setInitial(dexterity.getCur()); constitution.setInitial(constitution.getCur()); intelligence.setInitial(intelligence.getCur()); piety.setInitial(piety.getCur()); if(deity) { switch(deity) { case ARAMON: case ARACHNUS: alignment = -100; break; case ENOCH: case LINOTHAN: case KAMIRA: alignment = 100; break; } } if(cClass == LICH) alignment = -100; } //********************************************************************* // CustomCrt //********************************************************************* CustomCrt::CustomCrt() { community = parents = brothers = sisters = social = education = height = weight = 0; hair = eyes = skin = ""; } //********************************************************************* // getCommunity //********************************************************************* bool Create::getCommunity(Socket* sock, char* str, int mode) { if(mode == Create::doPrint) { sock->print("\nYour Community\n\n"); // these match up with the defines in CustomCrt sock->printColor(" [^Wa^x] You lived in the wilderness, shunning contact with most of your community.\n"); sock->printColor(" [^Wb^x] Your home was a small hamlet far from major cities.\n"); sock->printColor(" [^Wc^x] You lived in village that saw a fair amount of trading.\n"); sock->printColor(" [^Wd^x] The large town you grew up in was fairly well known.\n"); sock->printColor(" [^We^x] You grew up in a major city.\n\n"); sock->askFor(": "); Create::newline(sock); sock->setState(CUSTOM_COMMUNITY); } else if(mode == Create::doWork) { switch(str[0]) { case 'a': case 'b': case 'c': case 'd': case 'e': // these match up with the defines in CustomCrt, so we can just assign sock->getPlayer()->custom.community = str[0]-'a'+1; break; default: sock->printColor("Invalid selection: ^W%s\n", str); sock->askFor("Choose one: "); Create::newline(sock); sock->setState(CUSTOM_COMMUNITY); return(false); } } return(true); } //********************************************************************* // doFamily //********************************************************************* void Create::doFamily(Player* player, int mode) { if(mode == 1) { player->custom.parents = CustomCrt::PARENTS_UNKNOWN; return; } // siblings int i = 0; if(mode == 3) i = mrand(1,3); else if(mode == 4) i = mrand(4, 10); while(i) { if(mrand(0,1)) player->custom.sisters++; else player->custom.brothers++; i--; } switch(mrand(1,6)) { case 1: player->custom.parents = CustomCrt::PARENTS_DEAD; break; case 2: player->custom.parents = CustomCrt::PARENTS_MOTHER_DEAD; break; case 3: player->custom.parents = CustomCrt::PARENTS_FATHER_DEAD; break; // 50% chance of them being alive default: player->custom.parents = CustomCrt::PARENTS_ALIVE; break; } } //********************************************************************* // getFamily //********************************************************************* bool Create::getFamily(Socket* sock, char* str, int mode) { if(mode == Create::doPrint) { sock->print("\nYour Family\n\n"); sock->printColor(" [^Wa^x] You were orphaned as a child and have no family.\n"); sock->printColor(" [^Wb^x] You are an only child.\n"); sock->printColor(" [^Wc^x] You grew up in a small family with 1-3 siblings.\n"); sock->printColor(" [^Wd^x] The grew up in a large family with 4-10 siblings.\n\n"); sock->askFor(": "); Create::newline(sock); sock->setState(CUSTOM_FAMILY); } else if(mode == Create::doWork) { switch(str[0]) { case 'a': case 'b': case 'c': case 'd': doFamily(sock->getPlayer(), str[0]-'a'+1); break; default: sock->printColor("Invalid selection: ^W%s\n", str); sock->askFor("Choose one: "); Create::newline(sock); sock->setState(CUSTOM_FAMILY); return(false); } } return(true); } //********************************************************************* // getSocial //********************************************************************* bool Create::getSocial(Socket* sock, char* str, int mode) { CustomCrt *custom = &sock->getPlayer()->custom; if(mode == Create::doPrint) { sock->print("\nYour Social Status\n\n"); if(custom->parents == CustomCrt::PARENTS_UNKNOWN) sock->printColor(" [^Wa^x] You were an outcast in society.\n"); else sock->printColor(" [^Wa^x] You and your family were outcasts in society.\n"); if(custom->community != CustomCrt::COMMUNITY_OUTCAST) { sock->printColor(" [^Wb^x] You were considered a criminal (justly so or not).\n"); sock->printColor(" [^Wc^x] You grew up poor and on the lowest rungs of society.\n"); sock->printColor(" [^Wd^x] You had to work hard to provide for yourself, but were able to manage.\n"); if(custom->community != CustomCrt::COMMUNITY_HAMLET) { if(custom->parents == CustomCrt::PARENTS_UNKNOWN) sock->printColor(" [^We^x] Your life was easier than most as you were fairly well off.\n"); else sock->printColor(" [^We^x] Your life was easier than most as you and your family were fairly well off.\n"); if(custom->community != CustomCrt::COMMUNITY_VILLAGE && custom->parents != CustomCrt::PARENTS_UNKNOWN) { sock->printColor(" [^Wf^x] You and your family were well off in society and did not need to worry about much.\n"); sock->printColor(" [^Wg^x] Being of noble descent, you and your family were well known in the community.\n"); } } } sock->print("\n"); sock->askFor(": "); Create::newline(sock); sock->setState(CUSTOM_SOCIAL); } else if(mode == Create::doWork) { if( (str[0] > 'a' && custom->community == CustomCrt::COMMUNITY_OUTCAST) || (str[0] > 'd' && custom->community == CustomCrt::COMMUNITY_HAMLET) || (str[0] > 'e' && (custom->community == CustomCrt::COMMUNITY_VILLAGE || custom->parents == CustomCrt::PARENTS_UNKNOWN)) ) str[0] = 'z'; switch(str[0]) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': custom->social = str[0]-'a'+1; break; default: sock->printColor("Invalid selection: ^W%s\n", str); sock->askFor("Choose one: "); Create::newline(sock); sock->setState(CUSTOM_SOCIAL); return(false); } } return(true); } //********************************************************************* // getEducation //********************************************************************* bool Create::getEducation(Socket* sock, char* str, int mode) { CustomCrt *custom = &sock->getPlayer()->custom; if(mode == Create::doPrint) { sock->print("\nYour Education\n\n"); sock->printColor(" [^Wa^x] You have no formal education.\n"); if(custom->community != CustomCrt::COMMUNITY_OUTCAST && custom->social != CustomCrt::SOCIAL_OUTCAST) { sock->printColor(" [^Wb^x] You trained as an apprentice to a trader, crafstman, or farmer.\n"); sock->printColor(" [^Wc^x] You attended a local school and received a basic education.\n"); if(custom->community != CustomCrt::COMMUNITY_HAMLET && custom->social > CustomCrt::SOCIAL_LOWER) { sock->printColor(" [^Wd^x] You received a decent education or were tutored in several subject areas.\n"); sock->printColor(" [^We^x] You attended a large university and received an official degree.\n"); } } sock->askFor(": "); Create::newline(sock); sock->setState(CUSTOM_EDUCATION); } else if(mode == Create::doWork) { if( (str[0] > 'a' && (custom->community == CustomCrt::COMMUNITY_OUTCAST || custom->social == CustomCrt::SOCIAL_OUTCAST)) || (str[0] > 'c' && (custom->community == CustomCrt::COMMUNITY_HAMLET || custom->social <= CustomCrt::SOCIAL_LOWER)) ) str[0] = 'z'; switch(str[0]) { case 'a': case 'b': case 'c': case 'd': case 'e': custom->education = str[0]-'a'+1; break; default: sock->printColor("Invalid selection: ^W%s\n", str); sock->askFor("Choose one: "); Create::newline(sock); sock->setState(CUSTOM_EDUCATION); return(false); } } return(true); } //********************************************************************* // calcHeight //********************************************************************* int Create::calcHeight(int race, int mode) { switch(mode) { case 1: // shorter return(mrand(1,50)); case 3: // taller return(mrand(100,150)); default: // normal return(mrand(50,100)); } } //********************************************************************* // getHeight //********************************************************************* bool Create::getHeight(Socket* sock, char* str, int mode) { if(mode == Create::doPrint) { sock->print("\nYour Height\n\n"); sock->printColor(" [^Wa^x] You are shorter than most members of your race.\n"); sock->printColor(" [^Wb^x] Your height is average.\n"); sock->printColor(" [^Wc^x] You are taller than most members of your race.\n\n"); sock->askFor(": "); Create::newline(sock); sock->setState(CUSTOM_HEIGHT); } else if(mode == Create::doWork) { switch(str[0]) { case 'a': case 'b': case 'c': sock->getPlayer()->custom.height = Create::calcHeight(sock->getPlayer()->getRace(), str[0]-'a'+1); break; default: sock->printColor("Invalid selection: ^W%s\n", str); sock->askFor("Choose one: "); Create::newline(sock); sock->setState(CUSTOM_HEIGHT); return(false); } } return(true); } //********************************************************************* // calcWeight //********************************************************************* int Create::calcWeight(int race, int mode) { switch(mode) { case 1: // thinner return(mrand(1,50)); case 3: // stockier return(mrand(100,150)); default: // normal return(mrand(50,100)); } } //********************************************************************* // getWeight //********************************************************************* bool Create::getWeight(Socket* sock, char* str, int mode) { if(mode == Create::doPrint) { sock->print("\nYour Weight\n\n"); sock->printColor(" [^Wa^x] You are thinner than most members of your race.\n"); sock->printColor(" [^Wb^x] Your weight is average.\n"); sock->printColor(" [^Wc^x] You are heavier than most members of your race.\n\n"); sock->askFor(": "); Create::newline(sock); sock->setState(CUSTOM_WEIGHT); } else if(mode == Create::doWork) { switch(str[0]) { case 'a': case 'b': case 'c': sock->getPlayer()->custom.weight = Create::calcWeight(sock->getPlayer()->getRace(), str[0]-'a'+1); break; default: sock->printColor("Invalid selection: ^W%s\n", str); sock->askFor("Choose one: "); Create::newline(sock); sock->setState(CUSTOM_WEIGHT); return(false); } } return(true); } //********************************************************************* // nameIsAllowed //********************************************************************* // Return: Is the name allowed? true/false // Parameters: // str: The name we're testing // sock: The socket to print error messages to bool nameIsAllowed(char *str, Socket* sock) { int i=0, nonalpha=0, len = strlen(str); if(!isalpha(str[0])) return(false); if(!checkWinFilename(sock, str)) return(false); if(len < 3) { sock->print("Name must be at least 3 characters.\n"); return(false); } if(len >= 20) { sock->print("Name must be less than 20 characters.\n"); return(false); } for(i=0; i< (int)strlen(str); i++) if(!isalpha(str[i])) nonalpha++; if(nonalpha && len < 6) { sock->print("Name must be at least 6 characters in order to contain a - or '.\n"); return(false); } if(nonalpha > 1) { sock->print("May not have more than one non-alpha character in your name.\n"); return(false); } for(i=0; i<len; i++) { if(!isalpha(str[i])) { sock->print("Name must be alphabetic.\n"); return(false); } } if(!parse_name(str)) { sock->print("That name is not allowed.\n"); return(false); } return(true); } //********************************************************************* // addDouble //********************************************************************* void Config::addDoubleLog(bstring forum1, bstring forum2) { if(forum1 == "" || forum2 == "") return; if(canDoubleLog(forum1, forum2)) return; accountDouble pair; pair.first = forum1; pair.second = forum2; accountDoubleLog.push_back(pair); gConfig->saveDoubleLog(); } //********************************************************************* // remDouble //********************************************************************* void Config::remDoubleLog(bstring forum1, bstring forum2) { std::list<accountDouble>::iterator it; if(forum1 == "" || forum2 == "") return; for(it = accountDoubleLog.begin(); it != accountDoubleLog.end() ; it++) { if( ((*it).first == forum1 && (*it).second == forum2) || ((*it).first == forum2 && (*it).second == forum1) ) { accountDoubleLog.erase(it); gConfig->saveDoubleLog(); return; } } } //********************************************************************* // canDoubleLog //********************************************************************* bool Config::canDoubleLog(bstring forum1, bstring forum2) const { std::list<accountDouble>::const_iterator it; if(forum1 == "" || forum2 == "") return(false); for(it = accountDoubleLog.begin(); it != accountDoubleLog.end() ; it++) { if( ((*it).first == forum1 && (*it).second == forum2) || ((*it).first == forum2 && (*it).second == forum1) ) return(true); } return(false); } //********************************************************************* // saveDoubleLog //********************************************************************* bool Config::loadDoubleLog() { xmlDocPtr xmlDoc; xmlNodePtr curNode, childNode; bstring account = ""; xmlDoc = xml::loadFile(CONFPATH "doubleLog.xml", "DoubleLog"); if(xmlDoc == NULL) return(false); curNode = xmlDocGetRootElement(xmlDoc); curNode = curNode->children; while(curNode && xmlIsBlankNode(curNode)) curNode = curNode->next; if(curNode == 0) { xmlFreeDoc(xmlDoc); return(false); } accountDoubleLog.clear(); while(curNode != NULL) { if(NODE_NAME(curNode, "Accounts")) { childNode = curNode->children; account = ""; while(childNode) { if(NODE_NAME(childNode, "Forum1") || NODE_NAME(childNode, "Forum2")) { if(account == "") { // cache! xml::copyToBString(account, childNode); } else { // add! addDoubleLog(account, xml::getBString(childNode)); account = ""; } } childNode = childNode->next; } } curNode = curNode->next; } xmlFreeDoc(xmlDoc); xmlCleanupParser(); return(true); } //********************************************************************* // saveDoubleLog //********************************************************************* void Config::saveDoubleLog() const { std::list<accountDouble>::const_iterator it; xmlDocPtr xmlDoc; xmlNodePtr rootNode, curNode; char filename[80]; xmlDoc = xmlNewDoc(BAD_CAST "1.0"); rootNode = xmlNewDocNode(xmlDoc, NULL, BAD_CAST "DoubleLog", NULL); xmlDocSetRootElement(xmlDoc, rootNode); for(it = accountDoubleLog.begin(); it != accountDoubleLog.end() ; it++) { curNode = xml::newStringChild(rootNode, "Accounts"); xml::saveNonNullString(curNode, "Forum1", (*it).first); xml::saveNonNullString(curNode, "Forum2", (*it).second); } sprintf(filename, "%s/doubleLog.xml", CONFPATH); xml::saveFile(filename, xmlDoc); xmlFreeDoc(xmlDoc); } //********************************************************************* // listDoubleLog //********************************************************************* void Config::listDoubleLog(const Player* viewer) const { std::list<accountDouble>::const_iterator it; viewer->printColor("^YAccounts that may double log:\n"); for(it = accountDoubleLog.begin(); it != accountDoubleLog.end() ; it++) { viewer->print(" %-20s %-20s\n", (*it).first.c_str(), (*it).second.c_str()); } }