/* 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-2012 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 "alchemy.h"
#include "mxp.h"
#include "socials.h"
#include <exception>
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 bstring 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.c_str());
return(false);
}
if(loadType == LS_BACKUP)
sprintf(filename, "%s/%s.bak.xml", Path::PlayerBackup, name.c_str());
else if(loadType == LS_CONVERT)
sprintf(filename, "%s/convert/%s.xml", Path::Player, name.c_str());
else // LS_NORMAL
sprintf(filename, "%s/%s.xml", Path::Player, name.c_str());
//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.c_str(), loadName.c_str());
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(false);
}
*player = new Player;
if(!*player)
merror("loadPlayer", FATAL);
// (*player)->setName( tmpStr);
(*player)->setName(xml::getProp(rootNode, "Name"));
//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, UniqueRoom **pRoom) {
CatRef cr;
cr.id = index;
return(loadRoom(cr, pRoom));
}
bool loadRoom(const CatRef cr, UniqueRoom **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);
(*pRoom)->registerMo();
}
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, "%s", 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, UniqueRoom **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");
bool toReturn = false;
if(cr.id == -1 || num == cr.id) {
*pRoom = new UniqueRoom;
if(!*pRoom)
merror("loadRoomFromFile", FATAL);
(*pRoom)->setVersion(xml::getProp(rootNode, "Version"));
(*pRoom)->readFromXml(rootNode);
toReturn = true;
}
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(toReturn);
}
//*********************************************************************
// 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 = getAsPlayer();
Monster *mMonster = getAsMonster();
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")) setName(xml::getBString(curNode));
else if(NODE_NAME(curNode, "Id")) setId(xml::getBString(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(currentLocation.room.id, curNode);
else if(NODE_NAME(curNode, "Room")) currentLocation.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, "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")) {
readObjects(curNode);
}
else if(NODE_NAME(curNode, "Pets")) {
readCreatures(curNode);
}
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();
if(getVersion() < "2.46l") {
upgradeStats();
}
if(isPlayer()) {
if(getVersion() < "2.47b") {
pPlayer->recordLevelInfo();
}
}
if(isPlayer()) {
if(getVersion() < "2.47b") {
#define P_OLD_MISTED 55 // Player is in mist form
if(flagIsSet(P_OLD_MISTED)) {
addEffect("mist", -1);
clearFlag(P_OLD_MISTED);
}
#define P_OLD_INCOGNITO 104 // DM/CT is incognito
if(flagIsSet(P_OLD_INCOGNITO)) {
addEffect("incognito", -1);
clearFlag(P_OLD_INCOGNITO);
}
}
if(getVersion() < "2.47a") {
// Update weapon skills
SkillMap::iterator skIt;
for(skIt = skills.begin() ; skIt != skills.end() ; ) {
Skill* skill = (*skIt++).second;
SkillInfo* parentSkill = skill->getSkillInfo();
if(!parentSkill)
continue;
bstring group = parentSkill->getGroup();
if(group.left(7) == "weapons" && group.length() > 6) {
bstring weaponSkillName = group.right(group.length() - 8);
Skill* weaponSkill = getSkill(weaponSkillName, false);
if(!weaponSkill) {
addSkill(weaponSkillName, skill->getGained());
} else {
if(weaponSkill->getGained() < skill->getGained()) {
weaponSkill->setGained(skill->getGained());
}
}
}
}
}
if(getVersion() < "2.46k" && knowsSkill("endurance")) {
remSkill("endurance");
#define P_RUNNING_OLD 56
clearFlag(P_RUNNING_OLD);
}
if(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(getVersion() < "2.45c" && getCastingType() == Divine) {
int skill = level;
if(isPureCaster() || isHybridCaster() || isStaff()) {
skill *= 10;
} else {
skill *= 7;
}
skill -= 5;
skill = MAX(0, skill);
addSkill("healing", skill);
addSkill("destruction", getSkillGained("evocation"));
addSkill("evil", getSkillGained("necromancy"));
addSkill("knowledge", getSkillGained("divination"));
addSkill("protection", getSkillGained("abjuration"));
addSkill("augmentation", getSkillGained("transmutation"));
addSkill("travel", getSkillGained("translocation"));
addSkill("creation", getSkillGained("conjuration"));
addSkill("trickery", getSkillGained("illusion"));
addSkill("good", skill);
addSkill("nature", skill);
remSkill("abjuration");
remSkill("conjuration");
remSkill("divination");
remSkill("enchantment");
remSkill("evocation");
remSkill("illusion");
remSkill("necromancy");
remSkill("translocation");
remSkill("transmutation");
}
if(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, "Plural")) xml::copyToBString(plural, curNode);
else 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); // monster do not save PreviousRoom
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, "Wrap")) xml::copyToNum(wrap, 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, "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, "ObjIncrease")) {
childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "Object")) {
CatRef cr;
cr.load(childNode);
objIncrease.push_back(cr);
}
childNode = childNode->next;
}
}
else if(NODE_NAME(curNode, "StoresRefunded")) {\
childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "Store")) {
CatRef cr;
cr.load(childNode);
storesRefunded.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;
if(getVersion() < "2.45") {
// Old format
while(childNode) {
if(NODE_NAME(childNode, "Quest")) {
int questNum = xml::toNum<int>(childNode);
questsCompleted.insert(std::pair<int,int>(questNum,1));
}
childNode = childNode->next;
}
} else {
// New Format
xmlNodePtr subNode;
while(childNode) {
if(NODE_NAME(childNode, "Quest")) {
int questNum = -1;
int numCompletions = 1;
subNode = childNode->children;
while(subNode) {
if(NODE_NAME(subNode, "Id")) {
questNum = xml::toNum<int>(subNode);
} else if(NODE_NAME(subNode, "Num")) {
numCompletions = xml::toNum<int>(subNode);
}
if(questNum != -1) {
questsCompleted.insert(std::pair<int,int>(questNum,numCompletions));
}
subNode = subNode->next;
}
}
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));
} else if(getVersion() < "2.46l") {
if(NODE_NAME(curNode, "LostExperience")) statistics.setExperienceLost(xml::toNum<unsigned long>(curNode));
}
}
//*********************************************************************
// load
//*********************************************************************
Skill::Skill(xmlNodePtr rootNode) {
xmlNodePtr curNode = rootNode->children;
reset();
while(curNode) {
if(NODE_NAME(curNode, "Name")) {
setName(xml::getBString(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) {
throw(std::runtime_error("Invalid Skill Xml"));
}
}
//*********************************************************************
// 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")) {
try {
Skill *skill = new Skill(curNode);
skills.insert(SkillMap::value_type(skill->getName(), skill));
} catch(...) {
std::cout << "Error loading skill for " << getName() << std::endl;
}
}
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, MudObject* pParent) {
xmlNodePtr curNode = rootNode->children;
while(curNode) {
if(NODE_NAME(curNode, "Effect")) {
try {
EffectInfo* newEffect = new EffectInfo(curNode);
if(newEffect) {
newEffect->setParent(pParent);
effectList.push_back(newEffect);
}
} catch(std::runtime_error &e) {
std::cout << "Error adding effect: " << e.what() << std::endl;
}
}
curNode = curNode->next;
}
}
//*********************************************************************
// readFromXml
//*********************************************************************
// Reads an object from the given xml document and root node
int Object::readFromXml(xmlNodePtr rootNode, std::list<bstring> *idList) {
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")) setName(xml::getBString(curNode));
else if(NODE_NAME(curNode, "Id")) setId(xml::getBString(curNode));
else if(NODE_NAME(curNode, "IdList") && idList != 0) {
childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "Id")) {
idList->push_back(xml::getBString(childNode));
}
childNode = childNode->next;
}
}
else if(NODE_NAME(curNode, "Plural")) xml::copyToBString(plural, curNode);
else if(NODE_NAME(curNode, "DroppedBy")) droppedBy.load(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")) setAdjustment(xml::toNum<short int>(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, "ChargesMax")) xml::copyToNum(chargesMax, curNode);
else if(NODE_NAME(curNode, "ChargesCur")) xml::copyToNum(chargesCur, 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, "CoinCost")) coinCost = xml::toNum<unsigned long>(curNode);
else if(NODE_NAME(curNode, "Deed")) deed.load(curNode);
else if(NODE_NAME(curNode, "ShopValue")) setShopValue(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")) {
readObjects(curNode);
}
else if(NODE_NAME(curNode, "Compass")) {
if(!compass)
compass = new MapMarker;
compass->load(curNode);
}
else if(NODE_NAME(curNode, "ObjIncrease")) {
if(!increase)
increase = new ObjIncrease;
increase->load(curNode);
// it wasnt good after all
if(!increase->isValid()) {
delete increase;
increase = 0;
}
}
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(version < "2.47c" && flagIsSet(O_WEAPON_CASTS)) {
// Version 2.46j added charges for casting weapons, versions before that
// used shots, items until 2.47c were bugged due to charges not being
// copied in doCopy() Initialize charges as 1/3rd of shots
chargesMax = shotsMax / 3;
chargesCur = shotsCur /3;
}
if(version < "2.47b" && flagIsSet(O_OLD_INVISIBLE)) {
addEffect("invisibility", -1);
clearFlag(O_OLD_INVISIBLE);
}
// 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 UniqueRoom::readFromXml(xmlNodePtr rootNode) {
xmlNodePtr curNode;
// xmlNodePtr childNode;
info.load(rootNode);
info.id = xml::getIntProp(rootNode, "Num");
setId(bstring("R") + info.rstr());
xml::copyPropToBString(version, rootNode, "Version");
curNode = rootNode->children;
// Start reading stuff in!
while(curNode) {
if(NODE_NAME(curNode, "Name")) setName(xml::getBString(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")) {
readObjects(curNode);
}
else if(NODE_NAME(curNode, "Creatures")) {
readCreatures(curNode);
}
else if(NODE_NAME(curNode, "Exits")) {
readExitsXml(curNode);
}
else if(NODE_NAME(curNode, "Effects")) effects.load(curNode, 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;
setName(xml::getProp(rootNode, "Name"));
//xml::copyPropToCString(name, rootNode, "Name");
curNode = rootNode->children;
// Start reading stuff in!
while(curNode) {
if(NODE_NAME(curNode, "Name")) setName(xml::getBString(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, "Direction")) direction = (Direction)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, "Description")) xml::copyToBString(description, 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);
else if(NODE_NAME(curNode, "Effects")) effects.load(curNode, this);
else if(NODE_NAME(curNode, "Hooks")) hooks.load(curNode);
// depreciated, but there's no version function
// TODO: Use room->getVersion()
else if(NODE_NAME(curNode, "Room")) target.room.load(curNode);
else if(NODE_NAME(curNode, "AreaRoom")) target.mapmarker.load(curNode);
curNode = curNode->next;
}
if(room) {
room->addExit(this);
#define X_OLD_INVISIBLE 1 // Invisible
if(room->getVersion() < "2.47b" && flagIsSet(X_OLD_INVISIBLE)) {
addEffect("invisibility", -1);
clearFlag(X_OLD_INVISIBLE);
}
}
escapeText();
return(0);
}
//*********************************************************************
// readObjects
//*********************************************************************
// Reads in objects and objrefs and adds them to the parent
void MudObject::readObjects(xmlNodePtr curNode) {
xmlNodePtr childNode = curNode->children;
Object* object=0, *object2=0;
CatRef cr;
int i=0,quantity=0;
Creature* cParent = getAsCreature();
// Monster* mParent = parent->getMonster();
// Player* pParent = parent->getPlayer();
UniqueRoom* rParent = getAsUniqueRoom();
Object* oParent = getAsObject();
std::list<bstring> *idList;
while(childNode) {
object = 0;
object2 = 0;
quantity = xml::getIntProp(childNode, "Quantity");
if(quantity < 1)
quantity = 1;
if(quantity > 1)
idList = new std::list<bstring>;
else
idList = 0;
try {
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, idList);
} 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, idList);
}
}
}
if(object) {
std::list<bstring>::iterator idIt;
if(quantity > 1)
idIt = idList->begin();
for(i=0; i<quantity; i++) {
if(!i) {
object2 = object; // just a reference
} else {
object2 = new Object;
*object2 = *object;
}
try {
if(quantity > 1 && idIt != idList->end())
object2->setId(*idIt++);
// Add it to the appropriate parent
if(oParent) {
oParent->addObj(object2, false);
} else if(cParent) {
cParent->addObj(object2);
} else if(rParent) {
object2->addToRoom(rParent);
}
} catch(std::runtime_error &e) {
std::cout << "Error setting ID: " << e.what() << std::endl;
if(object2) {
delete object2;
object2 = 0;
}
}
}
}
} catch(std::runtime_error &e) {
std::cout << "Error loading object: " << e.what() << std::endl;
if(object != 0) {
delete object;
object = 0;
}
}
if(idList) {
delete idList;
idList = 0;
}
childNode = childNode->next;
}
}
//*********************************************************************
// readCreatures
//*********************************************************************
// Reads in creatures and crts refs and adds them to the parent
void MudObject::readCreatures(xmlNodePtr curNode) {
xmlNodePtr childNode = curNode->children;
Monster *mob=0;
CatRef cr;
Creature* cParent = getAsCreature();
// Monster* mParent = parent->getMonster();
// Player* pParent = parent->getPlayer();
UniqueRoom* rParent = getAsUniqueRoom();
Object* oParent = getAsObject();
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(cParent) {
// If we have a creature parent, we must be a pet
cParent->addPet(mob);
} else if(rParent) {
mob->addToRoom(rParent, 0);
} else if(oParent) {
// TODO: Not currently implemented
}
}
childNode = childNode->next;
}
}
//*********************************************************************
// readExitsXml
//*********************************************************************
void BaseRoom::readExitsXml(xmlNodePtr curNode) {
xmlNodePtr childNode = curNode->children;
Exit* ext=0;
AreaRoom* aRoom = getAsAreaRoom();
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->getName()))
delExit(ext);
} else
delExit(ext);
}
childNode = childNode->next;
}
}
//*********************************************************************
// loadSocials
//*********************************************************************
bool Config::loadSocials() {
xmlDocPtr xmlDoc;
xmlNodePtr curNode;
char filename[80];
// build an XML tree from a the file
sprintf(filename, "%s/socials.xml", Path::Code);
xmlDoc = xml::loadFile(filename, "Socials");
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, "Social")) {
SocialCommand* social = new SocialCommand(curNode);
if(social)
socials.insert(SocialMap::value_type(social->getName(),social));
}
curNode = curNode->next;
}
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(true);
}
int cmdSocial(Creature* creature, cmd* cmnd);
SocialCommand::SocialCommand(xmlNodePtr rootNode) {
rootNode = rootNode->children;
priority = 100;
auth = NULL;
description = "";
fn = cmdSocial;
wakeTarget = false;
rudeWakeTarget = false;
wakeRoom = false;
while(rootNode != NULL)
{
if(NODE_NAME(rootNode, "Name")) xml::copyToBString(name, rootNode);
else if(NODE_NAME(rootNode, "Description")) xml::copyToBString(description, rootNode);
else if(NODE_NAME(rootNode, "Priority")) xml::copyToNum(priority, rootNode);
else if(NODE_NAME(rootNode, "Script")) xml::copyToBString(script, rootNode);
else if(NODE_NAME(rootNode, "SelfNoTarget")) xml::copyToBString(selfNoTarget, rootNode);
else if(NODE_NAME(rootNode, "RoomNoTarget")) xml::copyToBString(roomNoTarget, rootNode);
else if(NODE_NAME(rootNode, "SelfOnTarget")) xml::copyToBString(selfOnTarget, rootNode);
else if(NODE_NAME(rootNode, "RoomOnTarget")) xml::copyToBString(roomOnTarget, rootNode);
else if(NODE_NAME(rootNode, "VictimOnTarget")) xml::copyToBString(victimOnTarget, rootNode);
else if(NODE_NAME(rootNode, "SelfOnSelf")) xml::copyToBString(selfOnSelf, rootNode);
else if(NODE_NAME(rootNode, "RoomOnSelf")) xml::copyToBString(roomOnSelf, rootNode);
else if(NODE_NAME(rootNode, "WakeTarget")) xml::copyToBool(wakeTarget, rootNode);
else if(NODE_NAME(rootNode, "RudeWakeTarget")) xml::copyToBool(rudeWakeTarget, rootNode);
else if(NODE_NAME(rootNode, "WakeRoom")) xml::copyToBool(wakeRoom, rootNode);
rootNode = rootNode->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", Path::Code);
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);
else if(NODE_NAME(rootNode, "PotionDisplayName")) xml::copyToBString(potionDisplayName, rootNode);
else if(NODE_NAME(rootNode, "PotionPrefix")) xml::copyToBString(potionPrefix, rootNode);
else if(NODE_NAME(rootNode, "Positive")) xml::copyToBool(positive, rootNode);
else if(NODE_NAME(rootNode, "BaseDuration")) xml::copyToNum(baseDuration, rootNode);
else if(NODE_NAME(rootNode, "BaseStrength")) xml::copyToNum(baseStrength, rootNode);
rootNode = rootNode->next;
}
}
//*********************************************************************
// loadMxpElements
//*********************************************************************
bool Config::loadMxpElements() {
xmlDocPtr xmlDoc;
xmlNodePtr curNode;
char filename[80];
// build an XML tree from a the file
sprintf(filename, "%s/mxp.xml", Path::Code);
xmlDoc = xml::loadFile(filename, "Mxp");
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, "MxpElement")) {
MxpElement* mxpElement = new MxpElement(curNode);
if(mxpElement) {
mxpElements.insert(std::pair<bstring, MxpElement*>(mxpElement->getName(), mxpElement));
if(mxpElement->isColor()) {
mxpColors.insert(std::pair<bstring, bstring>(mxpElement->getColor(), mxpElement->getName()));
}
}
}
curNode = curNode->next;
}
xmlFreeDoc(xmlDoc);
xmlCleanupParser();
return(true);
}
//bstring name;
//MxpType mxpType;
//bstring command;
//bstring hint;
//bool prompt;
//bstring attributes;
//bstring expire;
MxpElement::MxpElement(xmlNodePtr rootNode) {
rootNode = rootNode->children;
prompt = false;
while(rootNode != NULL)
{
if(NODE_NAME(rootNode, "Name")) xml::copyToBString(name, rootNode);
else if(NODE_NAME(rootNode, "Command")) xml::copyToBString(command, rootNode);
else if(NODE_NAME(rootNode, "Hint")) xml::copyToBString(hint, rootNode);
else if(NODE_NAME(rootNode, "Type")) xml::copyToBString(mxpType, rootNode);
else if(NODE_NAME(rootNode, "Prompt")) xml::copyToBool(prompt, rootNode);
else if(NODE_NAME(rootNode, "Attributes")) xml::copyToBString(attributes, rootNode);
else if(NODE_NAME(rootNode, "Expire")) xml::copyToBString(expire, rootNode);
else if(NODE_NAME(rootNode, "Color")) xml::copyToBString(color, rootNode);
rootNode = rootNode->next;
}
}
//*********************************************************************
// loadBans
//*********************************************************************
bool Config::loadBans() {
xmlDocPtr xmlDoc;
Ban *curBan=0;
xmlNodePtr cur;
char filename[80];
snprintf(filename, 80, "%s/bans.xml", Path::Config);
xmlDoc = xml::loadFile(filename, "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", Path::PlayerData);
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(std::runtime_error("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", Path::Code);
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;
}
updateSkillPointers();
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;
SkillInfo* skill=0;
while(curNode != NULL) {
if(NODE_NAME(curNode, "Skill")) {
try {
skill = new SkillInfo(curNode);
// A SkillInfo is not a SkillCommand, it only goes in the SkillInfo table
skills.insert(SkillInfoMap::value_type(skill->getName(), skill));
} catch(std::exception e) {
}
} else if(NODE_NAME(curNode, "SkillCommand")) {
try {
skill = new SkillCommand(curNode);
SkillCommand* skillCmd = dynamic_cast<SkillCommand*>(skill);
// All SkillCommands are also SkillInfos, put them in both tables
skills.insert(SkillInfoMap::value_type(skill->getName(), skill));
skillCommands.insert(SkillCommandMap::value_type(skill->getName(), skillCmd));
// Insert any aliases as well
for(bstring alias : skillCmd->aliases) {
skillCommands.insert(SkillCommandMap::value_type(alias, skillCmd));
}
} catch(std::exception e) {
}
}
curNode = curNode->next;
}
}
//*********************************************************************
// load
//*********************************************************************
SkillInfo::SkillInfo(xmlNodePtr rootNode) {
gainType = SKILL_NORMAL;
knownOnly = false;
xmlNodePtr curNode = rootNode->children;
bstring group;
bstring description;
while(curNode != NULL) {
readNode(curNode);
curNode = curNode->next;
}
if(name == "" || displayName == "") {
std::cout << "Invalid skill (Name:" << name << ", DisplayName: " << displayName << ")" << std::endl;
throw(std::runtime_error("Invalid SkillInfo XML"));
}
}
int cmdSkill(Creature* creature, cmd* cmnd);
SkillCommand::SkillCommand(xmlNodePtr rootNode) {
gainType = SKILL_NORMAL;
knownOnly = false;
usesAttackTimer = true;
xmlNodePtr curNode = rootNode->children;
priority = 100;
auth = NULL;
description = "";
targetType = TARGET_NONE;
fn = cmdSkill;
while(curNode != NULL) {
readNode(curNode);
curNode = curNode->next;
}
if(SkillInfo::name == "" || displayName == "") {
std::cout << "Invalid skillCommand (Name:" << SkillInfo::name << ", DisplayName: " << displayName << ")" << std::endl;
throw(std::runtime_error("Invalid Skill Command Xml"));
} else {
std::cout << "Found SkillCommand: " << SkillInfo::name << std::endl;
}
}
bool SkillInfo::readNode(xmlNodePtr curNode) {
bool retVal = true;
bstring tGroup;
if(NODE_NAME(curNode, "Name")) {
setName(xml::getBString(curNode));
} else if(NODE_NAME(curNode, "DisplayName")) {
xml::copyToBString(displayName, curNode);
} else if(NODE_NAME(curNode, "Base")) {
xml::copyToBString(tGroup, curNode);
if(!setBase(tGroup)) {
std::cout << "Error setting skill '" << name << "' base skill to '" << tGroup << "'" << std::endl;
abort();
}
} else if(NODE_NAME(curNode, "Group")) {
xml::copyToBString(tGroup, curNode);
if(!setGroup(tGroup)) {
std::cout << "Error setting skill '" << name << "' to group '" << tGroup << "'" << std::endl;
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);
} else {
// Nothing was read
retVal = false;
}
return(retVal);
}
bool SkillCommand::readNode(xmlNodePtr curNode) {
bool retVal = true;
// Try the base class method first, if they return true, it found something so continue on
if(SkillInfo::readNode(curNode)) {
retVal = true;
} else if(NODE_NAME(curNode, "Cooldown")) {
xml::copyToNum(cooldown, curNode);
} else if(NODE_NAME(curNode, "UsesAttackTimer")) {
xml::copyToBool(usesAttackTimer, curNode);
} else if(NODE_NAME(curNode, "Cooldown")) {
xml::copyToNum(cooldown, curNode);
} else if(NODE_NAME(curNode, "FailCooldown")) {
xml::copyToNum(failCooldown, curNode);
} else if(NODE_NAME(curNode, "Resources")) {
loadResources(curNode);
} else if(NODE_NAME(curNode, "Offensive")) {
xml::copyToBool(offensive, curNode);
} else if(NODE_NAME(curNode, "Alias")) {
aliases.push_back(xml::getBString(curNode));
} else if(NODE_NAME(curNode, "TargetType")) {
bstring tType = xml::getBString(curNode);
if(tType == "Creature")
targetType = TARGET_CREATURE;
else if(tType == "Monster")
targetType = TARGET_MONSTER;
else if(tType == "Player")
targetType = TARGET_PLAYER;
else if(tType == "Object")
targetType = TARGET_OBJECT;
else if(tType == "Exit")
targetType = TARGET_EXIT;
else if(tType == "Any" || tType == "All" || tType == "MudObject")
targetType = TARGET_MUDOBJECT;
else if(tType == "Self")
targetType = TARGET_NONE;
} else if(NODE_NAME(curNode, "Script")) {
xml::copyToBString(pyScript, curNode);
} else {
retVal = false;
}
return(retVal);
}
void SkillCommand::loadResources(xmlNodePtr rootNode) {
xmlNodePtr curNode = rootNode->children;
while(curNode != NULL) {
if(NODE_NAME(curNode, "Resource")) {
resources.push_back(SkillCost(curNode));
}
curNode = curNode->next;
}
}
SkillCost::SkillCost(xmlNodePtr rootNode) {
resource = RES_NONE;
cost = 0;
xmlNodePtr curNode = rootNode->children;
while(curNode != NULL) {
if(NODE_NAME(curNode, "Type")) {
bstring resourceStr;
xml::copyToBString(resourceStr, curNode);
if(resourceStr.equals("Gold", false)) {
resource = RES_GOLD;
} else if(resourceStr.equals("Mana", false) || resourceStr.equals("Mp")) {
resource = RES_MANA;
} else if(resourceStr.equals("HitPoints", false) || resourceStr.equals("Hp")) {
resource = RES_HIT_POINTS;
} else if(resourceStr.equals("Focus", false)) {
resource = RES_FOCUS;
} else if(resourceStr.equals("Energy", false)) {
resource = RES_ENERGY;
}
} else if(NODE_NAME(curNode, "Cost")) {
xml::copyToNum(cost, curNode);
}
curNode = curNode->next;
}
}
//*********************************************************************
// 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[255];
xmlNodePtr childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode , name)) {
i = xml::getIntProp(childNode, "Num");
if(i < maxProp) {
xml::copyToCString(temp, childNode);
j = strlen(temp);
if(j > (size - 1))
j = (size - 1);
temp[j] = '\0';
strcpy((char*)array + ( i * sizeof(char) * size), temp);
}
}
childNode = childNode->next;
}
}
//*********************************************************************
// loadAlchemyEffects
//*********************************************************************
AlchemyEffect::AlchemyEffect(xmlNodePtr curNode) {
quality=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 statName = "";
while(childNode) {
if(NODE_NAME(childNode, "Stat")) {
statName = xml::getProp(childNode, "Name");
if(statName == "")
continue;
if(statName == "Strength") strength.load(childNode, statName);
else if(statName == "Dexterity") dexterity.load(childNode, statName);
else if(statName == "Constitution") constitution.load(childNode, statName);
else if(statName == "Intelligence") intelligence.load(childNode, statName);
else if(statName == "Piety") piety.load(childNode, statName);
else if(statName == "Hp") hp.load(childNode, statName);
else if(statName == "Mp") mp.load(childNode, statName);
else if(statName == "Focus") {
Player* player = getAsPlayer();
if(player)
player->focus.load(childNode, statName);
}
}
childNode = childNode->next;
}
}
//*********************************************************************
// load
//*********************************************************************
// Loads a single stat into the given stat pointer
bool Stat::load(xmlNodePtr curNode, bstring statName) {
xmlNodePtr childNode = curNode->children;
name = statName;
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, "Initial")) xml::copyToNum(initial, childNode);
else if(NODE_NAME(childNode, "Modifiers")) loadModifiers(childNode);
childNode = childNode->next;
}
return(true);
}
bool Stat::loadModifiers(xmlNodePtr curNode) {
xmlNodePtr childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "StatModifier")) {
StatModifier* mod = new StatModifier(childNode);
if(mod->getName().equals("")) {
delete mod;
} else {
modifiers.insert(ModifierMap::value_type(mod->getName(), mod));
}
childNode = childNode->next;
}
}
return(true);
}
StatModifier::StatModifier(xmlNodePtr curNode) {
xmlNodePtr childNode = curNode->children;
while(childNode) {
if(NODE_NAME(childNode, "Name")) xml::copyToBString(name, childNode);
else if(NODE_NAME(childNode, "ModAmt")) xml::copyToNum(modAmt, childNode);
else if(NODE_NAME(childNode, "ModType")) modType = (ModifierType)xml::toNum<unsigned short>(childNode);
childNode = childNode->next;
}
}
//*********************************************************************
// 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;
}
}
void DroppedBy::load(xmlNodePtr rootNode) {
xmlNodePtr curNode = rootNode->children;
while(curNode) {
if(NODE_NAME(curNode, "Name")) xml::copyToBString(name, curNode);
else if(NODE_NAME(curNode, "Index")) xml::copyToBString(index, curNode);
else if(NODE_NAME(curNode, "ID")) xml::copyToBString(id, curNode);
else if(NODE_NAME(curNode, "Type")) xml::copyToBString(type, curNode);
curNode = curNode->next;
}
}