/*
* files-xml-read.cpp
* Used to read objects/rooms/creatures etc from xml files
* ____ _
* | _ \ ___ __ _| |_ __ ___ ___
* | |_) / _ \/ _` | | '_ ` _ \/ __|
* | _ < __/ (_| | | | | | | \__ \
* |_| \_\___|\__,_|_|_| |_| |_|___/
*
* 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
*
*/
/* Web Editor
* _ _ ____ _______ ______
* | \ | |/ __ \__ __| ____|
* | \| | | | | | | | |__
* | . ` | | | | | | | __|
* | |\ | |__| | | | | |____
* |_| \_|\____/ |_| |______|
*
* If you change anything here, make sure the changes are reflected in the web
* editor! Either edit the PHP yourself or tell Dominus to make the changes.
*/
#include "mud.h"
#include "effects.h"
#include "bans.h"
#include "guilds.h"
#include "factions.h"
#include "version.h"
#include "specials.h"
#include "calendar.h"
#include "quests.h"
#include "unique.h"
#include "magic.h"
#include "alchemy.h"
extern int objRefSaveFlags[];
// TODO: Make a function that will use an xml reader to only parse the player to find
// name and password
//*********************************************************************
// loadPlayer
//*********************************************************************
// Attempt to load the player named 'name' into the address given
// return 0 on success, -1 on failure
bool loadPlayer(const char* name, Player** player, LoadType loadType) {
xmlDocPtr xmlDoc;
xmlNodePtr rootNode;
char filename[256];
bstring pass = "", loadName = "";
if(!checkWinFilename(NULL, name)) {
printf("Failed lookup on player %s due to checkWinFilename.\n", name);
return(false);
}
if(loadType == LS_BACKUP)
sprintf(filename, "%s/%s.bak.xml", BACKUPPATH, name);
else if(loadType == LS_CONVERT)
sprintf(filename, "%s/convert/%s.xml", PLAYERPATH, name);
else // LS_NORMAL
sprintf(filename, "%s/%s.xml", PLAYERPATH, name);
//printf("Attempting to load player %s from file %s.\n", name, filename);
if((xmlDoc = xml::loadFile(filename, "Player")) == NULL)
return(false);
rootNode = xmlDocGetRootElement(xmlDoc);
loadName = xml::getProp(rootNode, "Name");
if(loadName != name) {
printf("Error loading %s, found %s instead!\n", name, loadName.c_str());
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(false);
}
*player = new Player;
if(!*player)
merror("loadPlayer", FATAL);
// strcpy((*player)->name, tmpStr);
xml::copyPropToCString((*player)->name, rootNode, "Name");
xml::copyPropToBString(pass, rootNode, "Password");
(*player)->setPassword(pass);
//xml::copyPropToBString((*player)->version, rootNode, "Version");
(*player)->setLastLogin(xml::getIntProp(rootNode, "LastLogin"));
// If we get here, we should be loading the correct player, so start reading them in
(*player)->readFromXml(rootNode);
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(true);
}
//*********************************************************************
// loadMonster
//*********************************************************************
bool loadMonster(int index, Monster ** pMonster) {
CatRef cr;
cr.id = index;
return(loadMonster(cr, pMonster));
}
bool loadMonster(const CatRef cr, Monster ** pMonster) {
if(!validMobId(cr))
return(false);
// Check if monster is already loaded, and if so return pointer
if(gConfig->monsterInQueue(cr)) {
gConfig->frontMonsterQueue(cr);
*pMonster = new Monster;
gConfig->getMonsterQueue(cr, pMonster);
} else {
// Otherwise load the monster and return a pointer to the newly loaded monster
// Load the creature from it's file
if(!loadMonsterFromFile(cr, pMonster))
return(false);
gConfig->addMonsterQueue(cr, pMonster);
}
(*pMonster)->fd = -1;
(*pMonster)->lasttime[LT_TICK].ltime =
(*pMonster)->lasttime[LT_TICK_SECONDARY].ltime =
(*pMonster)->lasttime[LT_TICK_HARMFUL].ltime = time(0);
(*pMonster)->lasttime[LT_TICK].interval =
(*pMonster)->lasttime[LT_TICK_SECONDARY].interval = 60;
(*pMonster)->lasttime[LT_TICK_HARMFUL].interval = 30;
(*pMonster)->getMobSave();
return(true);
}
//*********************************************************************
// loadObject
//*********************************************************************
bool loadObject(int index, Object** pObject) {
CatRef cr;
cr.id = index;
return(loadObject(cr, pObject));
}
bool loadObject(const CatRef cr, Object** pObject) {
if(!validObjId(cr))
return(false);
// Check if object is already loaded, and if so return pointer
if(gConfig->objectInQueue(cr)) {
gConfig->frontObjectQueue(cr);
*pObject = new Object;
gConfig->getObjectQueue(cr, pObject);
}
// Otherwise load the object and return a pointer to the newly loaded object
else {
// Load the object from it's file
if(!loadObjectFromFile(cr, pObject))
return(false);
gConfig->addObjectQueue(cr, pObject);
}
if(pObject) {
// Quest items are now auto NO-DROP
if((*pObject)->getQuestnum()) {
(*pObject)->setFlag(O_NO_DROP);
}
// cannot steal scrolls
if((*pObject)->getType() == SCROLL) {
(*pObject)->setFlag(O_NO_STEAL);
}
}
return(true);
}
//*********************************************************************
// loadRoom
//*********************************************************************
bool loadRoom(int index, Room **pRoom) {
CatRef cr;
cr.id = index;
return(loadRoom(cr, pRoom));
}
bool loadRoom(const CatRef cr, Room **pRoom) {
if(!validRoomId(cr))
return(false);
// If the room is already loaded, return it
if(gConfig->roomInQueue(cr)) {
gConfig->frontRoomQueue(cr);
gConfig->getRoomQueue(cr, pRoom);
} else {
// Otherwise load the room and return it
if(!loadRoomFromFile(cr, pRoom))
return(false);
gConfig->addRoomQueue(cr, pRoom);
}
return(true);
}
//*********************************************************************
// loadMonsterFromFile
//*********************************************************************
bool loadMonsterFromFile(const CatRef cr, Monster **pMonster, bstring filename) {
xmlDocPtr xmlDoc;
xmlNodePtr rootNode;
int num=0;
if(filename == "")
filename = monsterPath(cr);
//printf("Attempting to load creature %d from %s\n", index, filename);
if((xmlDoc = xml::loadFile(filename.c_str(), "Creature")) == NULL)
return(false);
if(xmlDoc == NULL) {
printf("Error parsing file %s\n", filename.c_str());
return(false);
}
rootNode = xmlDocGetRootElement(xmlDoc);
num = xml::getIntProp(rootNode, "Num");
if(cr.id == -1 || num == cr.id) {
*pMonster = new Monster;
if(!*pMonster)
merror("loadMonsterFromFile", FATAL);
(*pMonster)->setVersion(rootNode);
(*pMonster)->readFromXml(rootNode);
if((*pMonster)->flagIsSet(M_TALKS)) {
loadCreature_tlk((*pMonster));
(*pMonster)->convertOldTalks();
}
}
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(true);
}
//*********************************************************************
// loadObjectFromFile
//*********************************************************************
bool loadObjectFromFile(const CatRef cr, Object** pObject) {
xmlDocPtr xmlDoc;
xmlNodePtr rootNode;
int num;
char filename[256];
sprintf(filename, objectPath(cr));
//printf("Attempting to load object %d from %s\n", index, filename);
if((xmlDoc = xml::loadFile(filename, "Object")) == NULL)
return(false);
if(xmlDoc == NULL) {
printf("Error parsing file %s\n", filename);
return(false);
}
rootNode = xmlDocGetRootElement(xmlDoc);
num = xml::getIntProp(rootNode, "Num");
if(num == cr.id) {
// BINGO: This is the object we want, read it in
*pObject = new Object;
if(!*pObject)
merror("loadObjectFile", FATAL);
xml::copyPropToBString((*pObject)->version, rootNode, "Version");
(*pObject)->readFromXml(rootNode);
}
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(true);
}
//*********************************************************************
// loadRoomFromFile
//*********************************************************************
// if we're loading only from a filename, get CatRef from file
bool loadRoomFromFile(const CatRef cr, Room **pRoom, bstring filename) {
xmlDocPtr xmlDoc;
xmlNodePtr rootNode;
int num;
if(filename == "")
filename = roomPath(cr);
//printf("Attempting to load room %d from file %s.\n", index, filename);
if((xmlDoc = xml::loadFile(filename.c_str(), "Room")) == NULL)
return(false);
rootNode = xmlDocGetRootElement(xmlDoc);
num = xml::getIntProp(rootNode, "Num");
if(cr.id == -1 || num == cr.id) {
*pRoom = new Room;
if(!*pRoom)
merror("loadRoomFromFile", FATAL);
(*pRoom)->setVersion(xml::getProp(rootNode, "Version"));
(*pRoom)->readFromXml(rootNode);
}
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(true);
}
//*********************************************************************
// readFromXml
//*********************************************************************
// Reads a creature from the given xml document and root node
int convertProf(Creature* player, Realm realm) {
int skill = player->getLevel()*7 + player->getLevel()*3 * mprofic(player, realm) / 100 - 5;
skill = MAX(0, skill);
return(skill);
}
int Creature::readFromXml(xmlNodePtr rootNode) {
xmlNodePtr curNode;
int i;
unsigned short c = 0;
Player *pPlayer = getPlayer();
Monster *mMonster = getMonster();
if(mMonster) {
mMonster->info.load(rootNode);
mMonster->info.id = xml::getIntProp(rootNode, "Num");
}
xml::copyPropToBString(version, rootNode, "Version");
curNode = rootNode->children;
// Start reading stuff in!
while(curNode) {
// Name will only be loaded for Monsters
if(NODE_NAME(curNode, "Name")) xml::copyToCString(name, curNode);
else if(NODE_NAME(curNode, "Description")) xml::copyToBString(description, curNode);
else if(NODE_NAME(curNode, "Keys")) {
loadStringArray(curNode, key, CRT_KEY_LENGTH, "Key", 3);
}
else if(NODE_NAME(curNode, "MoveTypes")) {
loadStringArray(curNode, movetype, CRT_MOVETYPE_LENGTH, "MoveType", 3);
}
else if(NODE_NAME(curNode, "Level")) setLevel(xml::toNum<unsigned short>(curNode), true);
else if(NODE_NAME(curNode, "Type")) setType(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "RoomNum")&& getVersion() < "2.34" ) xml::copyToNum(room.id, curNode);
else if(NODE_NAME(curNode, "Room")) room.load(curNode);
else if(NODE_NAME(curNode, "Race")) setRace(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "Class")) c = xml::toNum<unsigned short>(curNode);
else if(NODE_NAME(curNode, "AttackPower")) setAttackPower(xml::toNum<unsigned int>(curNode));
else if(NODE_NAME(curNode, "DefenseSkill")) {
if(mMonster) {
mMonster->setDefenseSkill(xml::toNum<int>(curNode));
}
}
else if(NODE_NAME(curNode, "WeaponSkill")) {
if(mMonster) {
mMonster->setWeaponSkill(xml::toNum<int>(curNode));
}
}
else if(NODE_NAME(curNode, "Class2")) {
if(pPlayer) {
pPlayer->setSecondClass(xml::toNum<unsigned short>(curNode));
} else if(mMonster) {
// TODO: Dom: for compatability, remove when possible
mMonster->setMobTrade(xml::toNum<unsigned short>(curNode));
}
}
else if(NODE_NAME(curNode, "Alignment")) setAlignment(xml::toNum<short>(curNode));
else if(NODE_NAME(curNode, "Armor")) setArmor(xml::toNum<unsigned int>(curNode));
else if(NODE_NAME(curNode, "Experience")) setExperience(xml::toNum<unsigned long>(curNode));
else if(NODE_NAME(curNode, "Deity")) setDeity(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "Clan")) setClan(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "PoisonDuration")) setPoisonDuration(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "PoisonDamage")) setPoisonDamage(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "CurrentLanguage")) xml::copyToNum(current_language, curNode);
else if(NODE_NAME(curNode, "Coins")) coins.load(curNode);
else if(NODE_NAME(curNode, "Realms")) {
xml::loadNumArray<unsigned long>(curNode, realm, "Realm", MAX_REALM-1);
}
else if(NODE_NAME(curNode, "Proficiencies")) {
long proficiency[6];
zero(proficiency, sizeof(proficiency));
xml::loadNumArray<long>(curNode, proficiency, "Proficiency", 6);
// monster jail rooms shouldn't be stored here
if(mMonster && mMonster->getVersion() < "2.42b") {
mMonster->setCastChance(proficiency[0]);
mMonster->rescue[0].setArea("misc");
mMonster->rescue[0].id = proficiency[1];
mMonster->rescue[1].setArea("misc");
mMonster->rescue[1].id = proficiency[2];
mMonster->setMaxLevel(proficiency[3]);
mMonster->jail.setArea("misc");
mMonster->jail.id = proficiency[4];
}
}
else if(NODE_NAME(curNode, "Dice")) damage.load(curNode);
else if(NODE_NAME(curNode, "Skills")) {
loadSkills(curNode);
}
else if(NODE_NAME(curNode, "Factions")) {
loadFactions(curNode);
}
else if(NODE_NAME(curNode, "Effects")) {
effects.load(curNode, this);
}
else if(NODE_NAME(curNode, "SpecialAttacks")) {
loadAttacks(curNode);
}
else if(NODE_NAME(curNode, "InitialStats")) {
// TODO: remove
short ist[5];
xml::loadNumArray<short>(curNode, ist, "Stat", 5);
strength.setInitial(ist[0]);
dexterity.setInitial(ist[1]);
constitution.setInitial(ist[2]);
intelligence.setInitial(ist[3]);
piety.setInitial(ist[4]);
}
else if(NODE_NAME(curNode, "Stats")) {
loadStats(curNode);
}
else if(NODE_NAME(curNode, "Flags")) {
// Clear flags before loading incase we're loading a reference creature
for(i=0; i<CRT_FLAG_ARRAY_SIZE; i++)
flags[i] = 0;
loadBits(curNode, flags);
}
else if(NODE_NAME(curNode, "Spells")) {
loadBits(curNode, spells);
}
else if(NODE_NAME(curNode, "Quests")) {
loadBits(curNode, quests);
}
else if(NODE_NAME(curNode, "Languages")) {
loadBits(curNode, languages);
}
else if(NODE_NAME(curNode, "DailyTimers")) {
loadDailys(curNode, daily);
}
else if(NODE_NAME(curNode, "LastTimes")) {
loadLastTimes(curNode, lasttime);
}
else if(NODE_NAME(curNode, "SavingThrows")) {
loadSavingThrows(curNode, saves);
}
else if(NODE_NAME(curNode, "Inventory")) {
readObjectsXml(curNode, this, CRT);
}
else if(NODE_NAME(curNode, "Pets")) {
readCreaturesXml(curNode, this, CRT);
}
else if(NODE_NAME(curNode, "AreaRoom")) gConfig->areaInit(this, curNode);
else if(NODE_NAME(curNode, "Size")) setSize(whatSize(xml::toNum<int>(curNode)));
else if(NODE_NAME(curNode, "Hooks")) hooks.load(curNode);
// code for only players
else if(pPlayer) pPlayer->readXml(curNode);
// code for only monsters
else if(mMonster) mMonster->readXml(curNode);
curNode = curNode->next;
}
// run this here so effects are added properly
setClass(c);
convertOldEffects();
convertOldFlags();
if(isPlayer() && getVersion() < "2.43" && getClass() != BERSERKER) {
int skill = level;
if(isPureCaster() || isHybridCaster() || isStaff()) {
skill *= 10;
} else {
skill *= 7;
}
skill -= 5;
skill = MAX(0, skill);
addSkill("abjuration", skill);
addSkill("conjuration", skill);
addSkill("divination", skill);
addSkill("enchantment", skill);
addSkill("evocation", skill);
addSkill("illusion", skill);
addSkill("necromancy", skill);
addSkill("translocation", skill);
addSkill("transmutation", skill);
addSkill("fire", convertProf(this, FIRE));
addSkill("water", convertProf(this, WATER));
addSkill("earth", convertProf(this, EARTH));
addSkill("air", convertProf(this, WIND));
addSkill("cold", convertProf(this, COLD));
addSkill("electric", convertProf(this, ELEC));
}
if(isPlayer() && getClass() == LICH && getVersion() < "2.43b" && !spellIsKnown(S_SAP_LIFE))
learnSpell(S_SAP_LIFE);
setVersion();
if(size == NO_SIZE && race)
size = gConfig->getRace(race)->getSize();
escapeText();
return(0);
}
//*********************************************************************
// readXml
//*********************************************************************
void Monster::readXml(xmlNodePtr curNode) {
xmlNodePtr childNode;
if(NODE_NAME(curNode, "CarriedItems")) {
loadCarryArray(curNode, carry, "Carry", 10);
}
else if(NODE_NAME(curNode, "LoadAggro")) setLoadAggro(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "LastMod")) xml::copyToCString(last_mod, curNode);
// get rid of these after conversion
else if(NODE_NAME(curNode, "StorageRoom") && getVersion() < "2.34")
setLoadAggro(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "BoundRoom") && getVersion() < "2.34")
setSkillLevel(xml::toNum<int>(curNode));
else if(NODE_NAME(curNode, "SkillLevel")) setSkillLevel(xml::toNum<int>(curNode));
else if(NODE_NAME(curNode, "ClassAggro")) {
loadBits(curNode, cClassAggro);
}
else if(NODE_NAME(curNode, "RaceAggro")) {
loadBits(curNode, raceAggro);
}
else if(NODE_NAME(curNode, "DeityAggro")) {
loadBits(curNode, deityAggro);
}
else if(NODE_NAME(curNode, "Attacks")) {
loadStringArray(curNode, attack, CRT_ATTACK_LENGTH, "Attack", 3);
}
else if(NODE_NAME(curNode, "Talk")) xml::copyToBString(talk, curNode);
else if(NODE_NAME(curNode, "TalkResponses")) {
childNode = curNode->children;
TalkResponse* newTalk;
while(childNode) {
if(NODE_NAME(childNode, "TalkResponse")) {
if((newTalk = new TalkResponse(childNode)) != NULL) {
responses.push_back(newTalk);
}
}
childNode = childNode->next;
}
}
else if(NODE_NAME(curNode, "TradeTalk")) xml::copyToCString(ttalk, curNode);
else if(NODE_NAME(curNode, "NumWander")) setNumWander(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "MagicResistance")) setMagicResistance(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "MobTrade")) setMobTrade(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "AssistMobs")) {
loadCatRefArray(curNode, assist_mob, "Mob", NUM_ASSIST_MOB);
}
else if(NODE_NAME(curNode, "EnemyMobs")) {
loadCatRefArray(curNode, enemy_mob, "Mob", NUM_ENEMY_MOB);
}
else if(NODE_NAME(curNode, "PrimeFaction")) {
xml::copyToBString(primeFaction, curNode);
}
else if(NODE_NAME(curNode, "AggroString")) xml::copyToCString(aggroString, curNode);
else if(NODE_NAME(curNode, "MaxLevel")) setMaxLevel(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "Cast")) setCastChance(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "Jail")) jail.load(curNode);
else if(NODE_NAME(curNode, "Rescue")) loadCatRefArray(curNode, rescue, "Mob", NUM_RESCUE);
else if(NODE_NAME(curNode, "UpdateAggro")) setUpdateAggro(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "PkIn") && getVersion() < "2.42b") setUpdateAggro(xml::toNum<unsigned short>(curNode));
// Now handle version changes
else if(getVersion() < "2.21") {
//std::cout << "Loading mob pre version 2.21" << std::endl;
// Title was changed to AggroString as of 2.21
if(NODE_NAME(curNode, "Title")) xml::copyToCString(aggroString, curNode);
}
}
//*********************************************************************
// readXml
//*********************************************************************
void Player::readXml(xmlNodePtr curNode) {
xmlNodePtr childNode;
if(NODE_NAME(curNode, "Birthday")) {
birthday = new cDay;
birthday->load(curNode);
}
else if(NODE_NAME(curNode, "BoundRoom")) {
if(getVersion() < "2.42h")
bound.room.load(curNode);
else
bound.load(curNode);
}
else if(NODE_NAME(curNode, "PreviousRoom")) previousRoom.load(curNode);
else if(NODE_NAME(curNode, "Statistics")) statistics.load(curNode);
else if(NODE_NAME(curNode, "Bank")) bank.load(curNode);
else if(NODE_NAME(curNode, "Surname")) xml::copyToBString(surname, curNode);
else if(NODE_NAME(curNode, "Forum")) xml::copyToBString(forum, curNode);
else if(NODE_NAME(curNode, "Ranges"))
loadRanges(curNode, this);
else if(NODE_NAME(curNode, "Wimpy")) setWimpy(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "Songs")) {
loadBits(curNode, songs);
}
else if(NODE_NAME(curNode, "Anchors")) {
loadAnchors(curNode);
}
else if(NODE_NAME(curNode, "LastPassword")) xml::copyToBString(lastPassword, curNode);
else if(NODE_NAME(curNode, "PoisonedBy")) xml::copyToBString(poisonedBy, curNode);
else if(NODE_NAME(curNode, "AfflictedBy")) xml::copyToBString(afflictedBy, curNode);
else if(NODE_NAME(curNode, "ActualLevel")) setActualLevel(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "WeaponTrains")) setWeaponTrains(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "LastMod")) xml::copyToBString(oldCreated, curNode);
else if(NODE_NAME(curNode, "Created")) {
if(getVersion() < "2.43c")
xml::copyToBString(oldCreated, curNode);
else
xml::copyToNum(created, curNode);
}
else if(NODE_NAME(curNode, "Guild")) setGuild(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "GuildRank")) setGuildRank(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "TickDmg")) setTickDamage(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "NegativeLevels")) setNegativeLevels(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "LostExperience")) setLostExperience(xml::toNum<unsigned long>(curNode));
else if(NODE_NAME(curNode, "LastInterest")) setLastInterest(xml::toNum<long>(curNode));
else if(NODE_NAME(curNode, "Title")) setTitle(xml::getBString(curNode));
else if(NODE_NAME(curNode, "CustomColors")) xml::copyToCString(customColors, curNode);
else if(NODE_NAME(curNode, "Thirst")) setThirst(xml::toNum<unsigned short>(curNode));
else if(NODE_NAME(curNode, "RoomExp")) {
childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "Room")) {
CatRef cr;
cr.load(childNode);
roomExp.push_back(cr);
}
childNode = childNode->next;
}
}
else if(NODE_NAME(curNode, "Lore")) {
childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "Info")) {
CatRef cr;
cr.load(childNode);
lore.push_back(cr);
}
childNode = childNode->next;
}
}
else if(NODE_NAME(curNode, "Recipes")) {
childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "Recipe")) {
int i=0;
xml::copyToNum(i, childNode);
recipes.push_back(i);
}
childNode = childNode->next;
}
}
else if(NODE_NAME(curNode, "QuestsInProgress")) {
childNode = curNode->children;
QuestCompletion* qc;
while(childNode) {
if(NODE_NAME(childNode, "QuestCompletion")) {
qc = new QuestCompletion(childNode, this);
questsInProgress[qc->getParentQuest()->getId()] = qc;
}
childNode = childNode->next;
}
}
else if(NODE_NAME(curNode, "QuestsCompleted")) {
childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "Quest")) {
questsCompleted.push_back(xml::toNum<int>(childNode));
}
childNode = childNode->next;
}
}
else if(NODE_NAME(curNode, "Minions")) {
childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "Minion")) {
minions.push_back(xml::getBString(childNode));
}
childNode = childNode->next;
}
}
else if(getVersion() < "2.42i") {
if(NODE_NAME(curNode, "PkWon")) statistics.setPkwon(xml::toNum<unsigned long>(curNode));
else if(NODE_NAME(curNode, "PkIn")) statistics.setPkin(xml::toNum<unsigned long>(curNode));
}
}
//*********************************************************************
// load
//*********************************************************************
bool CrtSkill::load(xmlNodePtr rootNode) {
xmlNodePtr curNode = rootNode->children;
while(curNode) {
if(NODE_NAME(curNode, "Name")) {
xml::copyToBString(name, curNode);
} else if(NODE_NAME(curNode, "Gained")) {
xml::copyToNum(gained, curNode);
} else if(NODE_NAME(curNode, "GainBonus")) {
xml::copyToNum(gainBonus, curNode);
}
curNode = curNode->next;
}
if(name == "" || gained == 0) {
return(false);
}
return(true);
}
//*********************************************************************
// loadSkill
//*********************************************************************
bool Creature::loadSkill(xmlNodePtr rootNode) {
bstring name = "";
int gained=0;
xmlNodePtr curNode = rootNode->children;
while(curNode) {
if(NODE_NAME(curNode, "Name")) {
xml::copyToBString(name, curNode);
} else if(NODE_NAME(curNode, "Gained")) {
xml::copyToNum(gained, curNode);
}
curNode = curNode->next;
}
if(name != "" && gained != 0) {
CrtSkill* skill = new CrtSkill(name, gained);
skills[name] = skill;
return(true);
}
return(false);
}
//*********************************************************************
// loadFaction
//*********************************************************************
bool Creature::loadFaction(xmlNodePtr rootNode) {
bstring name = "";
int regard=0;
xmlNodePtr curNode = rootNode->children;
while(curNode) {
if(NODE_NAME(curNode, "Name")) {
xml::copyToBString(name, curNode);
} else if(NODE_NAME(curNode, "Regard")) {
xml::copyToNum(regard, curNode);
}
curNode = curNode->next;
}
// players; load faction even if 0
if(name != "" && (regard != 0 || isPlayer())) {
factions[name] = regard;
return(true);
}
return(false);
}
//*********************************************************************
// loadSkills
//*********************************************************************
void Creature::loadSkills(xmlNodePtr rootNode) {
xmlNodePtr curNode = rootNode->children;
while(curNode) {
if(NODE_NAME(curNode, "Skill")) {
CrtSkill *skill = new CrtSkill();
if(skill->load(curNode)) {
skills[skill->getName()] = skill;
} else {
delete skill;
}
}
curNode = curNode->next;
}
}
//*********************************************************************
// loadFactions
//*********************************************************************
void Creature::loadFactions(xmlNodePtr rootNode) {
xmlNodePtr curNode = rootNode->children;
while(curNode) {
if(NODE_NAME(curNode, "Faction")) {
loadFaction(curNode);
}
curNode = curNode->next;
}
}
//*********************************************************************
// load
//*********************************************************************
void Effects::load(xmlNodePtr rootNode, Creature* cParent, BaseRoom* rParent, Exit* xParent) {
xmlNodePtr curNode = rootNode->children;
while(curNode) {
if(NODE_NAME(curNode, "Effect")) {
try {
EffectInfo* newEffect = new EffectInfo(curNode, Effects::getParentType(cParent, rParent, xParent));
if(newEffect) {
newEffect->setParentCreature(cParent);
newEffect->setParentRoom(rParent);
newEffect->setParentExit(xParent);
list.push_back(newEffect);
}
} catch(bstring err) {
std::cout << "Error adding effect: " << err << std::endl;
}
}
curNode = curNode->next;
}
}
//*********************************************************************
// readFromXml
//*********************************************************************
// Reads an object from the given xml document and root node
int Object::readFromXml(xmlNodePtr rootNode) {
xmlNodePtr curNode, childNode;
info.load(rootNode);
info.id = xml::getIntProp(rootNode, "Num");
xml::copyPropToBString(version, rootNode, "Version");
curNode = rootNode->children;
// Start reading stuff in!
while(curNode) {
if(NODE_NAME(curNode, "Name")) xml::copyToCString(name, curNode);
else if(NODE_NAME(curNode, "Description")) xml::copyToBString(description, curNode);
else if(NODE_NAME(curNode, "LotteryNumbers")) {
xml::loadNumArray<short>(curNode, lotteryNumbers, "LotteryNum", 6);
}
else if(NODE_NAME(curNode, "UseOutput")) xml::copyToCString(use_output, curNode);
else if(NODE_NAME(curNode, "UseAttack")) xml::copyToCString(use_attack, curNode);
else if(NODE_NAME(curNode, "LastMod")) xml::copyToBString(lastMod, curNode);
else if(NODE_NAME(curNode, "Keys")) {
loadStringArray(curNode, key, OBJ_KEY_LENGTH, "Key", 3);
}
else if(NODE_NAME(curNode, "Weight")) xml::copyToNum(weight, curNode);
else if(NODE_NAME(curNode, "Type")) xml::copyToNum(type, curNode);
else if(NODE_NAME(curNode, "SubType")) xml::copyToBString(subType, curNode);
else if(NODE_NAME(curNode, "Adjustment")) xml::copyToNum(adjustment, curNode);
else if(NODE_NAME(curNode, "ShotsMax")) xml::copyToNum(shotsmax, curNode);
else if(NODE_NAME(curNode, "ShotsCur")) xml::copyToNum(shotscur, curNode);
else if(NODE_NAME(curNode, "Armor")) xml::copyToNum(armor, curNode);
else if(NODE_NAME(curNode, "WearFlag")) xml::copyToNum(wearflag, curNode);
else if(NODE_NAME(curNode, "MagicPower")) xml::copyToNum(magicpower, curNode);
else if(NODE_NAME(curNode, "Effect")) xml::copyToBString(effect, curNode);
else if(NODE_NAME(curNode, "EffectDuration")) xml::copyToNum(effectDuration, curNode);
else if(NODE_NAME(curNode, "EffectStrength")) xml::copyToNum(effectStrength, curNode);
else if(NODE_NAME(curNode, "Level")) xml::copyToNum(level, curNode);
else if(NODE_NAME(curNode, "Quality")) xml::copyToNum(quality, curNode);
else if(NODE_NAME(curNode, "RequiredSkill")) xml::copyToNum(requiredSkill, curNode);
else if(NODE_NAME(curNode, "Clan")) xml::copyToNum(clan, curNode);
else if(NODE_NAME(curNode, "Special")) xml::copyToNum(special, curNode);
else if(NODE_NAME(curNode, "QuestNum")) xml::copyToNum(questnum, curNode);
else if(NODE_NAME(curNode, "Bulk")) xml::copyToNum(bulk, curNode);
else if(NODE_NAME(curNode, "Size")) size = whatSize(xml::toNum<int>(curNode));
else if(NODE_NAME(curNode, "MaxBulk")) xml::copyToNum(maxbulk, curNode);
else if(NODE_NAME(curNode, "LotteryCycle")) xml::copyToNum(lotteryCycle, curNode);
else if(NODE_NAME(curNode, "MaxUnique")) xml::copyToNum(max_unique, curNode);
else if(NODE_NAME(curNode, "CoinCost")) coinCost = xml::toNum<unsigned long>(curNode);
else if(NODE_NAME(curNode, "Deed")) deed.load(curNode);
else if(NODE_NAME(curNode, "ShopValue")) shopValue = xml::toNum<unsigned long>(curNode);
else if(NODE_NAME(curNode, "Made")) xml::copyToNum(made, curNode);
else if(NODE_NAME(curNode, "KeyVal")) xml::copyToNum(keyVal, curNode);
else if(NODE_NAME(curNode, "Material")) material = (Material)xml::toNum<int>(curNode);
else if(NODE_NAME(curNode, "MinStrength")) xml::copyToNum(minStrength, curNode);
else if(NODE_NAME(curNode, "NumAttacks")) xml::copyToNum(numAttacks, curNode);
else if(NODE_NAME(curNode, "Delay")) xml::copyToNum(delay, curNode);
else if(NODE_NAME(curNode, "Extra")) xml::copyToNum(extra, curNode);
else if(NODE_NAME(curNode, "Recipe")) xml::copyToNum(recipe, curNode);
else if(NODE_NAME(curNode, "Value")) value.load(curNode);
else if(NODE_NAME(curNode, "InBag")) {
loadCatRefArray(curNode, in_bag, "Obj", 3);
}
else if(NODE_NAME(curNode, "Dice")) damage.load(curNode);
else if(NODE_NAME(curNode, "Flags")) {
loadBits(curNode, flags);
}
else if(NODE_NAME(curNode, "LastTimes")) {
loadLastTimes(curNode, lasttime);
}
else if(NODE_NAME(curNode, "SubItems")) {
readObjectsXml(curNode, this, OBJ);
}
else if(NODE_NAME(curNode, "Compass")) {
if(!compass)
compass = new MapMarker;
compass->load(curNode);
}
else if(NODE_NAME(curNode, "AlchemyEffects")) {
loadAlchemyEffects(curNode);
}
else if(NODE_NAME(curNode, "Hooks")) hooks.load(curNode);
else if(NODE_NAME(curNode, "RandomObjects")) {
childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "RandomObject")) {
CatRef cr;
cr.load(childNode);
randomObjects.push_back(cr);
}
childNode = childNode->next;
}
}
else if(NODE_NAME(curNode, "Owner")) xml::copyToBString(questOwner, curNode);
// Now handle version changes
else if(getVersion() < "2.41" ) {
if(NODE_NAME(curNode, "DeedLow")) deed.low.load(curNode);
else if(NODE_NAME(curNode, "DeedHigh")) xml::copyToNum(deed.high, curNode);
} else if(getVersion() < "2.42b") {
if(NODE_NAME(curNode, "SpecialThree")) xml::copyToNum(effectDuration, curNode);
}
curNode = curNode->next;
}
if(getType() == KEY && getVersion() < "2.43b") {
setKey(damage.getNumber());
damage.setNumber(0);
}
// make sure uniqueness stays intact
setFlag(O_UNIQUE);
if(!gConfig->getUnique(this))
clearFlag(O_UNIQUE);
escapeText();
return(0);
}
//*********************************************************************
// readFromXml
//*********************************************************************
// Reads a room from the given xml document and root node
int Room::readFromXml(xmlNodePtr rootNode) {
xmlNodePtr curNode;
// xmlNodePtr childNode;
info.load(rootNode);
info.id = xml::getIntProp(rootNode, "Num");
xml::copyPropToBString(version, rootNode, "Version");
curNode = rootNode->children;
// Start reading stuff in!
while(curNode) {
if(NODE_NAME(curNode, "Name")) xml::copyToCString(name, curNode);
else if(NODE_NAME(curNode, "ShortDescription")) xml::copyToBString(short_desc, curNode);
else if(NODE_NAME(curNode, "LongDescription")) xml::copyToBString(long_desc, curNode);
else if(NODE_NAME(curNode, "Fishing")) xml::copyToBString(fishing, curNode);
else if(NODE_NAME(curNode, "Faction")) xml::copyToBString(faction, curNode);
else if(NODE_NAME(curNode, "LastModBy")) xml::copyToCString(last_mod, curNode);
else if(NODE_NAME(curNode, "LastModTime")) xml::copyToCString(lastModTime, curNode);
else if(NODE_NAME(curNode, "LastPlayer")) xml::copyToCString(lastPly, curNode);
else if(NODE_NAME(curNode, "LastPlayerTime")) xml::copyToCString(lastPlyTime, curNode);
else if(NODE_NAME(curNode, "LowLevel")) xml::copyToNum(lowLevel, curNode);
else if(NODE_NAME(curNode, "HighLevel")) xml::copyToNum(highLevel, curNode);
else if(NODE_NAME(curNode, "MaxMobs")) xml::copyToNum(maxmobs, curNode);
else if(NODE_NAME(curNode, "Trap")) xml::copyToNum(trap, curNode);
else if(NODE_NAME(curNode, "TrapExit")) trapexit.load(curNode);
else if(NODE_NAME(curNode, "TrapWeight")) xml::copyToNum(trapweight, curNode);
else if(NODE_NAME(curNode, "TrapStrength")) xml::copyToNum(trapstrength, curNode);
else if(NODE_NAME(curNode, "BeenHere")) xml::copyToNum(beenhere, curNode);
else if(NODE_NAME(curNode, "Track")) track.load(curNode);
else if(NODE_NAME(curNode, "Wander")) wander.load(curNode);
else if(NODE_NAME(curNode, "RoomExp")) xml::copyToNum(roomExp, curNode);
else if(NODE_NAME(curNode, "Flags")) {
// No need to clear flags, no room refs
loadBits(curNode, flags);
}
else if(NODE_NAME(curNode, "PermMobs")) {
loadCrLastTimes(curNode, permMonsters);
}
else if(NODE_NAME(curNode, "PermObjs")) {
loadCrLastTimes(curNode, permObjects);
}
else if(NODE_NAME(curNode, "LastTimes")) {
loadLastTimes(curNode, lasttime);
}
else if(NODE_NAME(curNode, "Objects")) {
readObjectsXml(curNode, this, ROOM);
}
else if(NODE_NAME(curNode, "Creatures")) {
readCreaturesXml(curNode, this, ROOM);
}
else if(NODE_NAME(curNode, "Exits")) {
readExitsXml(curNode);
}
else if(NODE_NAME(curNode, "Effects")) effects.load(curNode, 0, this);
else if(NODE_NAME(curNode, "Size")) size = whatSize(xml::toNum<int>(curNode));
else if(NODE_NAME(curNode, "Hooks")) hooks.load(curNode);
// load old tracks
if(getVersion() < "2.32d") {
if(NODE_NAME(curNode, "TrackExit")) track.setDirection(xml::getBString(curNode));
else if(NODE_NAME(curNode, "TrackSize")) track.setSize(whatSize(xml::toNum<int>(curNode)));
else if(NODE_NAME(curNode, "TrackNum")) track.setNum(xml::toNum<int>(curNode));
}
// load old wander info
if(getVersion() < "2.33b") {
if(NODE_NAME(curNode, "Traffic")) wander.setTraffic(xml::toNum<int>(curNode));
else if(NODE_NAME(curNode, "RandomMonsters")) {
loadCatRefArray(curNode, wander.random, "Mob", NUM_RANDOM_SLOTS);
}
}
if(getVersion() < "2.42e") {
if(NODE_NAME(curNode, "Special")) xml::copyToNum(maxmobs, curNode);
}
curNode = curNode->next;
}
escapeText();
addEffectsIndex();
return(0);
}
//*********************************************************************
// readFromXml
//*********************************************************************
// Reads a exit from the given xml document and root node
int Exit::readFromXml(xmlNodePtr rootNode, BaseRoom* room) {
xmlNodePtr curNode;
xml::copyPropToCString(name, rootNode, "Name");
curNode = rootNode->children;
// Start reading stuff in!
while(curNode) {
if(NODE_NAME(curNode, "Name")) xml::copyToCString(name, curNode);
else if(NODE_NAME(curNode, "Keys")) {
loadStringArray(curNode, desc_key, EXIT_KEY_LENGTH, "Key", 3);
}
else if(NODE_NAME(curNode, "Level")) xml::copyToNum(level, curNode);
else if(NODE_NAME(curNode, "Trap")) xml::copyToNum(trap, curNode);
else if(NODE_NAME(curNode, "Key")) xml::copyToNum(key, curNode);
else if(NODE_NAME(curNode, "KeyArea")) xml::copyToBString(keyArea, curNode);
else if(NODE_NAME(curNode, "Size")) size = whatSize(xml::toNum<int>(curNode));
else if(NODE_NAME(curNode, "Toll")) xml::copyToNum(toll, curNode);
else if(NODE_NAME(curNode, "PassPhrase")) xml::copyToBString(passphrase, curNode);
else if(NODE_NAME(curNode, "PassLang")) xml::copyToNum(passlang, curNode);
else if(NODE_NAME(curNode, "Open")) xml::copyToBString(open, curNode);
else if(NODE_NAME(curNode, "Enter")) { xml::copyToBString(enter, curNode); }
else if(NODE_NAME(curNode, "Flags")) {
// No need to clear flags, no exit refs
loadBits(curNode, flags);
}
else if(NODE_NAME(curNode, "Target")) target.load(curNode);
// depreciated, but there's no version function
else if(NODE_NAME(curNode, "Room")) target.room.load(curNode);
else if(NODE_NAME(curNode, "AreaRoom")) target.mapmarker.load(curNode);
else if(NODE_NAME(curNode, "Effects")) effects.load(curNode, 0, room, this);
else if(NODE_NAME(curNode, "Hooks")) hooks.load(curNode);
curNode = curNode->next;
}
escapeText();
return(0);
}
//*********************************************************************
// readObjectsXml
//*********************************************************************
// Reads in objects and objrefs and adds them to parent of given type
void readObjectsXml(xmlNodePtr curNode, void* parent, int type) {
xmlNodePtr childNode = curNode->children;
Object* object=0, *object2=0;
CatRef cr;
int i=0,quantity=0;
while(childNode) {
object = 0;
quantity = xml::getIntProp(childNode, "Quantity");
if(quantity < 1)
quantity = 1;
if(NODE_NAME(childNode, "Object")) {
// If it's a full object, read it in
object = new Object;
if(!object)
merror("loadObjectsXml", FATAL);
object->readFromXml(childNode);
} else if(NODE_NAME(childNode, "ObjRef")) {
// If it's an object reference, we want to first load the parent object
// and then use readObjectXml to update any fields that may have changed
cr.load(childNode);
cr.id = xml::getIntProp(childNode, "Num");
if(!validObjId(cr)) {
printf("Invalid object %s\n", cr.str().c_str());
} else {
if(loadObject(cr, &object)) {
// These two flags might be cleared on the reference object, so let
// that object set them if it wants to
object->clearFlag(O_HIDDEN);
object->clearFlag(O_CURSED);
object->readFromXml(childNode);
} else {
//printf("Error loading object %d.\n", num);
}
}
}
if(object && type == ROOM && object->flagIsSet(O_PORTAL)) {
delete object;
object = 0;
}
if(object) {
for(i=0; i<quantity; i++) {
if(!i) {
object2 = object; // just a reference
} else {
object2 = new Object;
*object2 = *object;
}
// Add it to the appropriate parent
if(type == OBJ) {
((Object*)parent)->addObj(object2);
} else if(type == PLY || type == CRT) {
((Creature *)parent)->addObj(object2);
} else if(type == ROOM) {
object2->addToRoom((Room*)parent);
}
}
}
childNode = childNode->next;
}
}
//*********************************************************************
// readCreaturesXml
//*********************************************************************
// Reads in creatures and crts refs and adds them to parent of given type
void readCreaturesXml(xmlNodePtr curNode, void* parent, int type) {
xmlNodePtr childNode = curNode->children;
Monster *mob=0;
CatRef cr;
while(childNode) {
mob = NULL;
if(NODE_NAME( childNode , "Creature")) {
// If it's a full creature, read it in
mob = new Monster;
if(!mob)
merror("loadCreaturesXml", FATAL);
mob->readFromXml(childNode);
} else if(NODE_NAME( childNode, "CrtRef")) {
// If it's an creature reference, we want to first load the parent creature
// and then use readCreatureXml to update any fields that may have changed
cr.load(childNode);
cr.id = xml::getIntProp( childNode, "Num" );
if(loadMonster(cr, &mob)) {
mob->readFromXml(childNode);
} else {
//printf("Unable to load creature %d\n", num);
}
}
if(mob != NULL) {
// Add it to the appropriate parent
if(type == PLY || type == CRT) {
addFollower((Creature *) parent, mob, FALSE);
//add_crt_crt(crt, (Creature *)parent);
} else if(type == ROOM) {
mob->addToRoom((Room*)parent, 0);
} else if(type == OBJ) {
// Umm, not implemented? Lets put this big ass goblin in my ivory coffer...yah....
}
}
childNode = childNode->next;
}
}
//*********************************************************************
// readExitsXml
//*********************************************************************
void BaseRoom::readExitsXml(xmlNodePtr curNode) {
xmlNodePtr childNode = curNode->children;
Exit* ext=0;
AreaRoom* aRoom = getAreaRoom();
while(childNode) {
if(NODE_NAME(childNode , "Exit")) {
ext = new Exit;
if(!ext)
merror("loadExitsXml", FATAL);
ext->readFromXml(childNode, this);
if(!ext->flagIsSet(X_PORTAL)) {
// moving cardinal exit on the overland?
if(ext->flagIsSet(X_MOVING) && aRoom && aRoom->updateExit(ext->name))
delete ext;
else
addExit(ext);
} else
delete ext;
}
childNode = childNode->next;
}
}
//*********************************************************************
// loadAlchemy
//*********************************************************************
bool Config::loadAlchemy() {
xmlDocPtr xmlDoc;
xmlNodePtr curNode;
char filename[80];
// build an XML tree from a the file
sprintf(filename, "%s/alchemy.xml", CONFPATH);
xmlDoc = xml::loadFile(filename, "Alchemy");
if(xmlDoc == NULL)
return(false);
curNode = xmlDocGetRootElement(xmlDoc);
curNode = curNode->children;
while(curNode && xmlIsBlankNode(curNode)) {
curNode = curNode->next;
}
if(curNode == 0) {
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(false);
}
clearAlchemy();
while(curNode != NULL) {
if(NODE_NAME(curNode, "AlchemyInfo")) {
AlchemyInfo* alcInfo = new AlchemyInfo(curNode);
if(alcInfo)
alchemy.push_back(alcInfo);
}
curNode = curNode->next;
}
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(true);
}
AlchemyInfo::AlchemyInfo(xmlNodePtr rootNode) {
rootNode = rootNode->children;
while(rootNode != NULL)
{
if(NODE_NAME(rootNode, "Name")) xml::copyToBString(name, rootNode);
else if(NODE_NAME(rootNode, "Action")) xml::copyToBString(action, rootNode);
else if(NODE_NAME(rootNode, "PythonScript")) xml::copyToBString(pythonScript, rootNode);
else if(NODE_NAME(rootNode, "Positive")) xml::copyToBool(positive, rootNode);
else if(NODE_NAME(rootNode, "Throwable")) xml::copyToBool(throwable, rootNode);
rootNode = rootNode->next;
}
}
//*********************************************************************
// loadBans
//*********************************************************************
bool Config::loadBans() {
xmlDocPtr xmlDoc;
Ban *curBan=0;
xmlNodePtr cur;
//char filename[80];
xmlDoc = xml::loadFile(CONFPATH "bans.xml", "Bans");
if(xmlDoc == NULL)
return(false);
cur = xmlDocGetRootElement(xmlDoc);
// numBans = 0;
// memset(banTable, 0, sizeof(banTable));
// First level we expect a Ban
cur = cur->children;
while(cur && xmlIsBlankNode(cur)) {
cur = cur->next;
}
if(cur == 0) {
xmlFreeDoc(xmlDoc);
return(false);
}
clearBanList();
while(cur != NULL) {
if((!strcmp((char*) cur->name, "Ban"))) {
curBan = new Ban(cur);
if(curBan != NULL)
bans.push_back(curBan);
}
cur = cur->next;
}
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(true);
}
//*********************************************************************
// Ban
//*********************************************************************
Ban::Ban(xmlNodePtr curNode) {
curNode = curNode->children;
while(curNode != NULL)
{
if(NODE_NAME(curNode, "Site")) xml::copyToBString(site, curNode);
else if(NODE_NAME(curNode, "Duration")) xml::copyToNum(duration, curNode);
else if(NODE_NAME(curNode, "UnbanTime")) xml::copyToNum(unbanTime, curNode);
else if(NODE_NAME(curNode, "BannedBy")) xml::copyToBString(by, curNode);
else if(NODE_NAME(curNode, "BanTime")) xml::copyToBString(time, curNode);
else if(NODE_NAME(curNode, "Reason")) xml::copyToBString(reason, curNode);
else if(NODE_NAME(curNode, "Password")) xml::copyToBString(password, curNode);
else if(NODE_NAME(curNode, "Suffix")) xml::copyToBool(isSuffix, curNode);
else if(NODE_NAME(curNode, "Prefix")) xml::copyToBool(isPrefix, curNode);
curNode = curNode->next;
}
}
//*********************************************************************
// loadGuilds
//*********************************************************************
// Causes the xml guild file to be parsed
bool Config::loadGuilds() {
xmlDocPtr xmlDoc;
GuildCreation *curCreation=0;
xmlNodePtr cur;
char filename[80];
// build an XML tree from a the file
sprintf(filename, "%s/guilds.xml", CONFPATH);
xmlDoc = xml::loadFile(filename, "Guilds");
if(xmlDoc == NULL)
return(false);
cur = xmlDocGetRootElement(xmlDoc);
gConfig->nextGuildId = xml::getIntProp(cur, "NextGuildId");
// xml::copyToNum(gConfig->nextGuildId, = toNum<int>((char *)xmlGetProp(cur, BAD_CAST "NextGuildId"));
// numGuilds = 0;
// memset(guildTable, 0, sizeof(guildTable));
// First level we expect a Guild
cur = cur->children;
while(cur && xmlIsBlankNode(cur))
cur = cur->next;
if(cur == 0) {
// DOH! Forgot to clean up stuff here...not that it happened, but would have been leaky
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(false);
}
clearGuildList();
Guild* guild;
while(cur != NULL) {
if(!strcmp((char *)cur->name, "Guild")) {
guild = new Guild(cur);
if(guild)
addGuild(guild);
}
if(!strcmp((char *)cur->name, "GuildCreation")) {
curCreation = parseGuildCreation(cur);
if(curCreation != NULL)
addGuildCreation(curCreation);
}
cur = cur->next;
}
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(true);
}
//*********************************************************************
// parseGuild
//*********************************************************************
// Parse an individual guild from a valid xml file
Guild::Guild(xmlNodePtr curNode) {
int guildId = xml::getIntProp(curNode, "ID");
if(guildId == 0)
throw new bstring("Invalid GuildID");
num = guildId;
gConfig->numGuilds = MAX(gConfig->numGuilds, guildId);
curNode = curNode->children;
while(curNode != NULL) {
if(NODE_NAME(curNode, "Name")) xml::copyToBString(name, curNode);
else if(NODE_NAME(curNode, "Leader")) xml::copyToBString(leader, curNode);
else if(NODE_NAME(curNode, "Level")) xml::copyToNum(level, curNode);
else if(NODE_NAME(curNode, "NumMembers")) xml::copyToNum(numMembers, curNode);
else if(NODE_NAME(curNode, "Members")) parseGuildMembers(curNode);
else if(NODE_NAME(curNode, "PkillsWon")) xml::copyToNum(pkillsWon, curNode);
else if(NODE_NAME(curNode, "PkillsIn")) xml::copyToNum(pkillsIn, curNode);
else if(NODE_NAME(curNode, "Points")) xml::copyToNum(points, curNode);
else if(NODE_NAME(curNode, "Bank")) bank.load(curNode);
curNode = curNode->next;
}
}
//*********************************************************************
// parseGuildCreation
//*********************************************************************
// Parse an individual guild from a valid xml file
GuildCreation * parseGuildCreation(xmlNodePtr cur) {
GuildCreation* gc = new GuildCreation;
if(gc == NULL) {
loge("Guild_Load: out of memory\n");
return(NULL);
}
bstring temp = "";
cur = cur->children;
while(cur != NULL) {
if(NODE_NAME(cur, "Name")) xml::copyToBString(gc->name, cur);
else if(NODE_NAME(cur, "Leader")) xml::copyToBString(gc->leader, cur);
else if(NODE_NAME(cur, "LeaderIp")) xml::copyToBString(gc->leaderIp, cur);
else if(NODE_NAME(cur, "Status")) xml::copyToNum(gc->status, cur);
else if(NODE_NAME(cur, "Supporter")) {
xml::copyToBString(temp, cur);
gc->supporters[temp] = xml::getProp(cur, "Ip");
gc->numSupporters++;
}
cur = cur->next;
}
return(gc);
}
//*********************************************************************
// parseGuildMembers
//*********************************************************************
void Guild::parseGuildMembers(xmlNodePtr cur) {
cur = cur->children;
while(cur != NULL) {
if(NODE_NAME(cur, "Member")) {
char *tmp = xml::getCString(cur);
addMember(tmp);
free(tmp);
}
cur = cur->next;
}
}
//*********************************************************************
// loadSkills
//*********************************************************************
bool Config::loadSkills() {
xmlDocPtr xmlDoc;
//GuildCreation * curCreation;
xmlNodePtr cur;
char filename[80];
// build an XML tree from a the file
sprintf(filename, "%s/skills.xml", CONFPATH);
xmlDoc = xml::loadFile(filename, "Skills");
if(xmlDoc == NULL)
return(false);
cur = xmlDocGetRootElement(xmlDoc);
cur = cur->children;
while(cur && xmlIsBlankNode(cur)) {
cur = cur->next;
}
if(cur == 0) {
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(false);
}
clearSkills();
while(cur != NULL) {
if(NODE_NAME(cur, "SkillGroups")) {
loadSkillGroups(cur);
} else if(NODE_NAME(cur, "Skills")) {
loadSkills(cur);
}
cur = cur->next;
}
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(true);
}
//*********************************************************************
// loadSkillGroups
//*********************************************************************
void Config::loadSkillGroups(xmlNodePtr rootNode) {
xmlNodePtr curNode = rootNode->children;
while(curNode != NULL) {
if(NODE_NAME(curNode, "SkillGroup")) {
loadSkillGroup(curNode);
}
curNode = curNode->next;
}
}
//*********************************************************************
// loadSkillGroup
//*********************************************************************
void Config::loadSkillGroup(xmlNodePtr rootNode) {
xmlNodePtr curNode = rootNode->children;
bstring name;
bstring displayName;
while(curNode != NULL) {
if(NODE_NAME(curNode, "Name")) {
xml::copyToBString(name, curNode);
} else if(NODE_NAME(curNode, "DisplayName")) {
xml::copyToBString(displayName, curNode);
}
curNode = curNode->next;
}
if(name != "" && displayName != "") {
skillGroups[name] = displayName;
}
return;
}
//*********************************************************************
// loadSkills
//*********************************************************************
void Config::loadSkills(xmlNodePtr rootNode) {
xmlNodePtr curNode = rootNode->children;
Skill* skill=0;
while(curNode != NULL) {
if(NODE_NAME(curNode, "Skill")) {
skill = new Skill;
if(skill->load(curNode) ) {
skills[skill->getName()] = skill;
} else {
delete skill;
}
skill = 0;
}
curNode = curNode->next;
}
}
//*********************************************************************
// load
//*********************************************************************
bool Skill::load(xmlNodePtr rootNode) {
xmlNodePtr curNode = rootNode->children;
bstring group;
bstring description;
while(curNode != NULL) {
if(NODE_NAME(curNode, "Name")) {
xml::copyToBString(name, curNode);
} else if(NODE_NAME(curNode, "DisplayName")) {
xml::copyToBString(displayName, curNode);
} else if(NODE_NAME(curNode, "Group")) {
xml::copyToBString(group, curNode);
if(!setGroup(group)) {
printf("Error setting skill '%s' to group '%s'", name.c_str(), group.c_str());
abort();
}
} else if(NODE_NAME(curNode, "Description")) {
xml::copyToBString(description, curNode);
} else if(NODE_NAME(curNode, "GainType")) {
bstring strGainType;
xml::copyToBString(strGainType, curNode);
if(strGainType == "Medium") {
gainType = SKILL_MEDIUM;
} else if(strGainType == "Hard") {
gainType = SKILL_HARD;
} else if(strGainType == "Normal") {
gainType = SKILL_NORMAL;
} else if(strGainType == "Easy") {
gainType = SKILL_EASY;
}
} else if(NODE_NAME(curNode, "KnownOnly")) {
xml::copyToBool(knownOnly, curNode);
}
curNode = curNode->next;
}
if(name == "" || displayName == "") {
printf("Invalid skill (Name:%s, DisplayName:%s)", name.c_str(), displayName.c_str());
return(false);
}
return(true);
}
//*********************************************************************
// loadCatRefArray
//*********************************************************************
void loadCatRefArray(xmlNodePtr curNode, std::map<int, CatRef>& array, const char* name, int maxProp) {
xmlNodePtr childNode = curNode->children;
int i=0;
while(childNode) {
if(NODE_NAME(childNode , name)) {
i = xml::getIntProp(childNode, "Num");
if(i >= 0 && i < maxProp)
array[i].load(childNode);
}
childNode = childNode->next;
}
}
//*********************************************************************
// loadCatRefArray
//*********************************************************************
void loadCatRefArray(xmlNodePtr curNode, CatRef array[], const char* name, int maxProp) {
xmlNodePtr childNode = curNode->children;
int i=0;
while(childNode) {
if(NODE_NAME(childNode , name)) {
i = xml::getIntProp(childNode, "Num");
if(i >= 0 && i < maxProp)
array[i].load(childNode);
}
childNode = childNode->next;
}
}
//*********************************************************************
// loadCarryArray
//*********************************************************************
void loadCarryArray(xmlNodePtr curNode, Carry array[], const char* name, int maxProp) {
xmlNodePtr childNode = curNode->children;
int i=0;
while(childNode) {
if(NODE_NAME(childNode , name)) {
i = xml::getIntProp(childNode, "Num");
if(i >= 0 && i < maxProp)
array[i].load(childNode);
}
childNode = childNode->next;
}
}
//*********************************************************************
// loadString Array
//*********************************************************************
// Since we can't easily pass in variable length arrays, we pass in a pointer to the array
// as well as the size of the array. Based on the size and current number being read in
// we do some pointer arithmetic and then memcpy to the appropriate location
// Note: Size MUST be accurate or you will get unpredictable results
void loadStringArray(xmlNodePtr curNode, void* array, int size, const char* name, int maxProp) {
int i=0, j=0;
char *temp;
xmlNodePtr childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode , name)) {
i = xml::getIntProp(childNode, "Num");
if(i < maxProp) {
// Note: The return from xml::getCString must be freed!
temp = xml::getCString(childNode);
if(temp) {
j = strlen(temp);
if(j > (size - 1))
j = (size - 1);
temp[j] = '\0';
memcpy((char*)array + ( i * sizeof(char) * size), temp, j + 1);
free(temp);
}
}
}
childNode = childNode->next;
}
}
//*********************************************************************
// loadAlchemyEffects
//*********************************************************************
AlchemyEffect::AlchemyEffect(xmlNodePtr curNode) {
duration = strength = 1;
xmlNodePtr childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "Effect")) {
effect = xml::getBString(childNode);
} else if(NODE_NAME(childNode, "Duration")) {
xml::copyToNum(duration, childNode);
} else if(NODE_NAME(childNode, "Strength")) {
xml::copyToNum(strength, childNode);
} else if(NODE_NAME(childNode, "Quality")) {
xml::copyToNum(quality, childNode);
}
childNode = childNode->next;
}
}
void Object::loadAlchemyEffects(xmlNodePtr curNode) {
int i=0;
xmlNodePtr childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "AlchemyEffect")) {
i = xml::getIntProp(childNode, "Num");
if(i>0) {
alchemyEffects[i] = AlchemyEffect(childNode);
}
}
childNode = childNode->next;
}
}
//*********************************************************************
// loadBits
//*********************************************************************
// Sets all bits it finds into the given bit array
void loadBits(xmlNodePtr curNode, char *bits) {
xmlNodePtr childNode = curNode->children;
int bit=0;
while(childNode) {
if(NODE_NAME(childNode, "Bit")) {
bit = xml::getIntProp(childNode, "Num");
// TODO: Sanity check bit
BIT_SET(bits, bit);
}
childNode = childNode->next;
}
}
//*********************************************************************
// loadDailys
//*********************************************************************
// This function will load all daily timers into the given dailys array
void loadDailys(xmlNodePtr curNode, struct daily* pDailys) {
xmlNodePtr childNode = curNode->children;
int i=0;
while(childNode) {
if(NODE_NAME(childNode, "Daily")) {
i = xml::getIntProp(childNode, "Num");
// TODO: Sanity check i
loadDaily(childNode, &pDailys[i]);
}
childNode = childNode->next;
}
}
//*********************************************************************
// loadDaily
//*********************************************************************
// This loads an individual daily into the provided pointer
void loadDaily(xmlNodePtr curNode, struct daily* pDaily) {
xmlNodePtr childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "Max")) xml::copyToNum(pDaily->max, childNode);
else if(NODE_NAME(childNode, "Current")) xml::copyToNum(pDaily->cur, childNode);
else if(NODE_NAME(childNode, "LastTime")) xml::copyToNum(pDaily->ltime, childNode);
childNode = childNode->next;
}
}
//*********************************************************************
// loadCrLastTimes
//*********************************************************************
// This function will load all crlasttimer into the given crlasttime array
void loadCrLastTimes(xmlNodePtr curNode, std::map<int, crlasttime>& pCrLastTimes) {
xmlNodePtr childNode = curNode->children;
int i=0;
while(childNode) {
if(NODE_NAME(childNode, "LastTime")) {
i = xml::getIntProp(childNode, "Num");
if(i >= 0 && i < NUM_PERM_SLOTS) {
struct crlasttime cr;
loadCrLastTime(childNode, &cr);
if(cr.cr.id)
pCrLastTimes[i] = cr;
}
}
childNode = childNode->next;
}
}
//*********************************************************************
// loadCrLastTime
//*********************************************************************
// Loads a single crlasttime into the given lasttime
void loadCrLastTime(xmlNodePtr curNode, struct crlasttime* pCrLastTime) {
xmlNodePtr childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "Interval")) xml::copyToNum(pCrLastTime->interval, childNode);
else if(NODE_NAME(childNode, "LastTime")) xml::copyToNum(pCrLastTime->ltime, childNode);
else if(NODE_NAME(childNode, "Misc")) pCrLastTime->cr.load(childNode);
childNode = childNode->next;
}
}
//*********************************************************************
// loadLastTimes
//*********************************************************************
// This function will load all lasttimer into the given lasttime array
void loadLastTimes(xmlNodePtr curNode, struct lasttime* pLastTimes) {
xmlNodePtr childNode = curNode->children;
int i=0;
while(childNode) {
if(NODE_NAME(childNode, "LastTime")) {
i = xml::getIntProp(childNode, "Num");
// TODO: Sanity check i
loadLastTime(childNode, &pLastTimes[i]);
}
childNode = childNode->next;
}
}
//*********************************************************************
// loadLastTime
//*********************************************************************
// Loads a single lasttime into the given lasttime
void loadLastTime(xmlNodePtr curNode, struct lasttime* pLastTime) {
xmlNodePtr childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "Interval")) xml::copyToNum(pLastTime->interval, childNode);
else if(NODE_NAME(childNode, "LastTime")) xml::copyToNum(pLastTime->ltime, childNode);
else if(NODE_NAME(childNode, "Misc")) xml::copyToNum(pLastTime->misc, childNode);
childNode = childNode->next;
}
}
//*********************************************************************
// loadAnchors
//*********************************************************************
// Loads all anchors into the given anchors array
void Player::loadAnchors(xmlNodePtr curNode) {
xmlNodePtr childNode = curNode->children;
int i=0;
while(childNode) {
if(NODE_NAME(childNode, "Anchor")) {
i = xml::getIntProp(childNode, "Num");
if(i >= 0 && i < MAX_DIMEN_ANCHORS && !anchor[i]) {
anchor[i] = new Anchor;
anchor[i]->load(childNode);
}
}
childNode = childNode->next;
}
}
//*********************************************************************
// loadSavingThrows
//*********************************************************************
// Loads all saving throws into the given array of saving throws
void loadSavingThrows(xmlNodePtr curNode, struct saves* pSavingThrows) {
xmlNodePtr childNode = curNode->children;
int i=0;
while(childNode) {
if(NODE_NAME(childNode, "SavingThrow")) {
i = xml::getIntProp(childNode, "Num");
// TODO: Sanity check i
loadSavingThrow(childNode, &pSavingThrows[i]);
}
childNode = childNode->next;
}
}
//*********************************************************************
// loadSavingThrows
//*********************************************************************
// Loads an individual saving throw
void loadSavingThrow(xmlNodePtr curNode, struct saves* pSavingThrow) {
xmlNodePtr childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "Chance")) xml::copyToNum(pSavingThrow->chance, childNode);
else if(NODE_NAME(childNode, "Gained")) xml::copyToNum(pSavingThrow->gained, childNode);
else if(NODE_NAME(childNode, "Misc")) xml::copyToNum(pSavingThrow->misc, childNode);
childNode = childNode->next;
}
}
//*********************************************************************
// loadRanges
//*********************************************************************
// Loads builder ranges into the provided creature
void loadRanges(xmlNodePtr curNode, Player *pPlayer) {
xmlNodePtr childNode = curNode->children;
int i=0;
while(childNode) {
if(NODE_NAME(childNode, "Range")) {
i = xml::getIntProp(childNode, "Num");
if(i >= 0 && i < MAX_BUILDER_RANGE)
pPlayer->bRange[i].load(childNode);
}
childNode = childNode->next;
}
}
//*********************************************************************
// loadStats
//*********************************************************************
// Loads all stats (strength, intelligence, hp, etc) into the given creature
void Creature::loadStats(xmlNodePtr curNode) {
xmlNodePtr childNode = curNode->children;
bstring stat = "";
while(childNode) {
if(NODE_NAME(childNode, "Stat")) {
stat = xml::getProp(childNode, "Name");
if(stat == "")
continue;
if(stat == "Strength") strength.load(childNode);
else if(stat == "Dexterity") dexterity.load(childNode);
else if(stat == "Constitution") constitution.load(childNode);
else if(stat == "Intelligence") intelligence.load(childNode);
else if(stat == "Piety") piety.load(childNode);
else if(stat == "Hp") hp.load(childNode);
else if(stat == "Mp") mp.load(childNode);
else if(stat == "Focus") {
Player* player = getPlayer();
if(player)
player->focus.load(childNode);
}
}
childNode = childNode->next;
}
}
//*********************************************************************
// load
//*********************************************************************
// Loads a single stat into the given stat pointer
bool Stat::load(xmlNodePtr curNode) {
xmlNodePtr childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "Current")) xml::copyToNum(cur, childNode);
else if(NODE_NAME(childNode, "Max")) xml::copyToNum(max, childNode);
else if(NODE_NAME(childNode, "TempMax")) xml::copyToNum(tmpMax, childNode);
else if(NODE_NAME(childNode, "Initial")) xml::copyToNum(initial, childNode);
childNode = childNode->next;
}
return(true);
}
//*********************************************************************
// loadAttacks
//*********************************************************************
void Creature::loadAttacks(xmlNodePtr rootNode) {
xmlNodePtr curNode = rootNode->children;
while(curNode) {
if(NODE_NAME(curNode, "SpecialAttack")) {
SpecialAttack* newAttack = new SpecialAttack(curNode);
if(newAttack) {
specials.push_back(newAttack);
}
}
curNode = curNode->next;
}
}