/* * playerClass.cpp * Player Class * ____ _ * | _ \ ___ __ _| |_ __ ___ ___ * | |_) / _ \/ _` | | '_ ` _ \/ __| * | _ < __/ (_| | | | | | | \__ \ * |_| \_\___|\__,_|_|_| |_| |_|___/ * * 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" //********************************************************************* // PlayerClass //********************************************************************* PlayerClass::PlayerClass(xmlNodePtr rootNode) { needDeity = false; numProf = 1; hasAutomaticStats = false; baseStrength=-1; baseDexterity=-1; baseConstitution=-1; baseIntelligence=-1; basePiety=-1; unarmedWeaponSkill = "bare-hand"; load(rootNode); } PlayerClass::~PlayerClass() { std::list<SkillGain*>::iterator bsIt; std::map<int, LevelGain*>::iterator lgIt; std::map<int, PlayerTitle*>::iterator tt; SkillGain* sGain; LevelGain* lGain; for(bsIt = baseSkills.begin() ; bsIt != baseSkills.end() ; bsIt++) { sGain = (*bsIt); delete sGain; } baseSkills.clear(); for(lgIt = levels.begin() ; lgIt != levels.end() ; lgIt++) { lGain = (*lgIt).second; delete lGain; } levels.clear(); for(tt = titles.begin() ; tt != titles.end() ; tt++) { PlayerTitle* p = (*tt).second; delete p; } titles.clear(); } //********************************************************************* // load //********************************************************************* void PlayerClass::load(xmlNodePtr rootNode) { // // Stuff gained on each additional level // std::map<int, LevelGain*> levels; id = xml::getIntProp(rootNode, "id"); xml::copyPropToBString(name, rootNode, "Name"); xmlNodePtr curNode = rootNode->children; while(curNode) { if(NODE_NAME(curNode, "Title")) { titles[1] = new PlayerTitle; titles[1]->load(curNode); } else if(NODE_NAME(curNode, "UnarmedWeaponSkill")) xml::copyToBString(unarmedWeaponSkill, curNode); else if(NODE_NAME(curNode, "NumProfs")) xml::copyToNum(numProf, curNode); else if(NODE_NAME(curNode, "NeedsDeity")) { int i=0; xml::copyToNum(i, curNode); if(i) needDeity = true; } else if(NODE_NAME(curNode, "Base")) { xmlNodePtr baseNode = curNode->children; while(baseNode) { if(NODE_NAME(baseNode, "Stats")) { xmlNodePtr statNode = baseNode->children; while(statNode) { if(NODE_NAME(statNode, "Hp")) { xml::copyToNum(baseHp, statNode); } else if(NODE_NAME(statNode, "Mp")) { xml::copyToNum(baseMp, statNode); } else if(NODE_NAME(statNode, "Strength")) { xml::copyToNum(baseStrength, statNode); checkAutomaticStats(); } else if(NODE_NAME(statNode, "Dexterity")) { xml::copyToNum(baseDexterity, statNode); checkAutomaticStats(); } else if(NODE_NAME(statNode, "Constitution")) { xml::copyToNum(baseConstitution, statNode); checkAutomaticStats(); } else if(NODE_NAME(statNode, "Intelligence")) { xml::copyToNum(baseIntelligence, statNode); checkAutomaticStats(); } else if(NODE_NAME(statNode, "Piety")) { xml::copyToNum(basePiety, statNode); checkAutomaticStats(); } statNode = statNode->next; } } else if(NODE_NAME(baseNode, "Dice")) damage.load(baseNode); else if(NODE_NAME(baseNode, "Skills")) { xmlNodePtr skillNode = baseNode->children; while(skillNode) { if(NODE_NAME(skillNode, "Skill")) { SkillGain* skillGain = new SkillGain(skillNode); baseSkills.push_back(skillGain); } skillNode = skillNode->next; } } baseNode = baseNode->next; } } else if(NODE_NAME(curNode, "Levels")) { xmlNodePtr levelNode = curNode->children; int lvl; while(levelNode) { if(NODE_NAME(levelNode, "Level")) { lvl = xml::getIntProp(levelNode, "Num"); if(lvl > 0) { levels[lvl] = new LevelGain(levelNode); } xmlNodePtr childNode = levelNode->children; while(childNode) { if(NODE_NAME(childNode, "Title")) { titles[lvl] = new PlayerTitle; titles[lvl]->load(childNode); } childNode = childNode->next; } } levelNode = levelNode->next; } } curNode = curNode->next; } } //********************************************************************* // getId //********************************************************************* int PlayerClass::getId() const { return(id); } //********************************************************************* // getName //********************************************************************* bstring PlayerClass::getName() const { return(name); } //********************************************************************* // getUnarmedWeaponSkill //********************************************************************* bstring PlayerClass::getUnarmedWeaponSkill() const { return(unarmedWeaponSkill); } //********************************************************************* // getSkillBegin //********************************************************************* std::list<SkillGain*>::const_iterator PlayerClass::getSkillBegin() { return(baseSkills.begin()); } //********************************************************************* // getSkillEnd //********************************************************************* std::list<SkillGain*>::const_iterator PlayerClass::getSkillEnd() { return(baseSkills.end()); } //********************************************************************* // getLevelBegin //********************************************************************* std::map<int, LevelGain*>::const_iterator PlayerClass::getLevelBegin() { return(levels.begin()); } //********************************************************************* // getLevelEnd //********************************************************************* std::map<int, LevelGain*>::const_iterator PlayerClass::getLevelEnd() { return(levels.end()); } //********************************************************************* // getBaseHp //********************************************************************* short PlayerClass::getBaseHp() { return(baseHp); } //********************************************************************* // getBaseMp //********************************************************************* short PlayerClass::getBaseMp() { return(baseMp); } //********************************************************************* // needsDeity //********************************************************************* bool PlayerClass::needsDeity() { return(needDeity); } //********************************************************************* // numProfs //********************************************************************* short PlayerClass::numProfs() { return(numProf); } //********************************************************************* // getLevelGain //********************************************************************* LevelGain* PlayerClass::getLevelGain(int lvl) { return(levels[lvl]); } //********************************************************************* // hasDefaultStats //********************************************************************* bool PlayerClass::hasDefaultStats() { return(hasAutomaticStats); } //********************************************************************* // setDefaultStats //********************************************************************* bool PlayerClass::setDefaultStats(Player* player) { if(!hasDefaultStats() || !player) return(false); player->strength.setInitial(baseStrength * 10); player->dexterity.setInitial(baseDexterity * 10); player->constitution.setInitial(baseConstitution * 10); player->intelligence.setInitial(baseIntelligence * 10); player->piety.setInitial(basePiety * 10); return(true); } //********************************************************************* // checkAutomaticStats //********************************************************************* void PlayerClass::checkAutomaticStats() { if(baseStrength != -1 && baseDexterity != -1 && baseConstitution != -1 && baseIntelligence != -1 && basePiety != -1) { std::cout << "Automatic stats registered for " << this->getName() << std::endl; hasAutomaticStats = true; } } //********************************************************************* // loadClasses //********************************************************************* bool Config::loadClasses() { xmlDocPtr xmlDoc; xmlNodePtr curNode; char filename[80]; snprintf(filename, 80, "%s/classes.xml", Path::Game); xmlDoc = xml::loadFile(filename, "Classes"); 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); } clearClasses(); bstring className = ""; while(curNode != NULL) { if(NODE_NAME(curNode, "Class")) { xml::copyPropToBString( className, curNode, "Name"); if(className != "") { if(classes.find(className) == classes.end()) { //printf("\n\tLoaded %s", className.c_str()); classes[className] = new PlayerClass(curNode); } else { printf("Error: Duplicate class: %s\n", className.c_str()); } } } curNode = curNode->next; } xmlFreeDoc(xmlDoc); xmlCleanupParser(); //printf("\n"); return(true); } //********************************************************************* // clearClasses //********************************************************************* void Config::clearClasses() { std::map<bstring, PlayerClass*>::iterator pcIt; for(pcIt = classes.begin() ; pcIt != classes.end() ; pcIt++) { //printf("Erasing class %s\n", ((*pcIt).first).c_str()); PlayerClass* pClass = (*pcIt).second; delete pClass; } classes.clear(); } //********************************************************************* // dmShowClasses //********************************************************************* int dmShowClasses(Player* admin, cmd* cmnd) { bool more = admin->isDm() && cmnd->num > 1 && !strcmp(cmnd->str[1], "more"); bool all = admin->isDm() && cmnd->num > 1 && !strcmp(cmnd->str[1], "all"); std::map<bstring, PlayerClass*>::iterator cIt; PlayerClass* pClass; SkillGain* sGain; bstring tmp; admin->printColor("Displaying Classes:%s\n", admin->isDm() ? " Type ^y*classlist more^x to view more, ^y*classlist all^x to view all information." : ""); for(cIt = gConfig->classes.begin() ; cIt != gConfig->classes.end() ; cIt++) { pClass = (*cIt).second; admin->printColor("Id: ^c%-2d^x Name: ^c%s\n", pClass->getId(), (*cIt).first.c_str()); if(more || all) { std::ostringstream cStr; std::map<int, PlayerTitle*>::iterator tt; //cStr << "Class: " << (*cIt).first << "\n"; cStr << " Base: " << pClass->getBaseHp() << "hp, " << pClass->getBaseMp() << "mp, " << "Dice: " << pClass->damage.str() << "\n" << " NumProfs: " << pClass->numProfs() << " NeedsDeity: " << (pClass->needsDeity() ? "^gYes" : "^rNo") << "^x\n"; std::list<SkillGain*>::const_iterator sgIt; if(all) { cStr << " Skills: "; for(sgIt = pClass->getSkillBegin() ; sgIt != pClass->getSkillEnd() ; sgIt++) { sGain = *sgIt; cStr << gConfig->getSkillDisplayName(sGain->getName()) << "(" << sGain->getGained() << ") "; } std::map<int, LevelGain*>::const_iterator lgIt; cStr << "\n Levels: "; for(lgIt = pClass->getLevelBegin() ; lgIt != pClass->getLevelEnd() ; lgIt ++) { LevelGain* lGain = (*lgIt).second; int lvl = (*lgIt).first; if(!lGain) { cStr << "\n ERROR: No level gain information found for " << pClass->getName() << " : " << lvl << "."; continue; } cStr << "\n " << lvl << ": " << lGain->getHp() << "HP, " << lGain->getMp() << "MP, St:" << lGain->getStatStr() << ", Sa:" << lGain->getSaveStr(); if(lGain->hasSkills()) { cStr << "\n Skills:"; for(sgIt = lGain->getSkillBegin() ; sgIt != lGain->getSkillEnd() ; sgIt++) { sGain = *sgIt; cStr << "\n " << gConfig->getSkillDisplayName(sGain->getName()) << "(" << sGain->getGained() << ") "; } } } cStr << "\n Titles: "; for(tt = pClass->titles.begin() ; tt != pClass->titles.end(); tt++) { PlayerTitle* title = (*tt).second; cStr << "\n Level: ^c" << (*tt).first << "^x" << " Male: ^c" << title->getTitle(true) << "^x" << " Female: ^c" << title->getTitle(false) << "^x"; } } cStr << "\n"; tmp = cStr.str(); admin->printColor("%s", tmp.c_str()); gServer->processOutput(); } } return(0); }