bool Vocations::parseVocationNode(xmlNodePtr p) { std::string strValue; int32_t intValue; float floatValue; if(xmlStrcmp(p->name, (const xmlChar*)"vocation")) return false; if(!readXMLInteger(p, "id", intValue)) { std::cout << "[Error - Vocations::parseVocationNode] Missing vocation id." << std::endl; return false; } Vocation* voc = new Vocation(intValue); if(readXMLString(p, "name", strValue)) voc->setName(strValue); if(readXMLString(p, "description", strValue)) voc->setDescription(strValue); if(readXMLString(p, "needpremium", strValue)) voc->setNeedPremium(booleanString(strValue)); if(readXMLInteger(p, "gaincap", intValue) || readXMLInteger(p, "gaincapacity", intValue)) voc->setGainCap(intValue); if(readXMLInteger(p, "gainhp", intValue) || readXMLInteger(p, "gainhealth", intValue)) voc->setGain(GAIN_HEALTH, intValue); if(readXMLInteger(p, "gainmana", intValue)) voc->setGain(GAIN_MANA, intValue); if(readXMLInteger(p, "gainhpticks", intValue) || readXMLInteger(p, "gainhealthticks", intValue)) voc->setGainTicks(GAIN_HEALTH, intValue); if(readXMLInteger(p, "gainhpamount", intValue) || readXMLInteger(p, "gainhealthamount", intValue)) voc->setGainAmount(GAIN_HEALTH, intValue); if(readXMLInteger(p, "gainmanaticks", intValue)) voc->setGainTicks(GAIN_MANA, intValue); if(readXMLInteger(p, "gainmanaamount", intValue)) voc->setGainAmount(GAIN_MANA, intValue); if(readXMLFloat(p, "manamultiplier", floatValue)) voc->setMultiplier(MULTIPLIER_MANA, floatValue); if(readXMLInteger(p, "attackspeed", intValue)) voc->setAttackSpeed(intValue); if(readXMLInteger(p, "basespeed", intValue)) voc->setBaseSpeed(intValue); if(readXMLInteger(p, "soulmax", intValue)) voc->setGain(GAIN_SOUL, intValue); if(readXMLInteger(p, "gainsoulamount", intValue)) voc->setGainAmount(GAIN_SOUL, intValue); if(readXMLInteger(p, "gainsoulticks", intValue)) voc->setGainTicks(GAIN_SOUL, intValue); if(readXMLString(p, "attackable", strValue)) voc->setAttackable(booleanString(strValue)); if(readXMLInteger(p, "fromvoc", intValue) || readXMLInteger(p, "fromvocation", intValue)) voc->setFromVocation(intValue); if(readXMLInteger(p, "lessloss", intValue)) voc->setLessLoss(intValue); xmlNodePtr configNode = p->children; while(configNode) { if(!xmlStrcmp(configNode->name, (const xmlChar*)"skill")) { if(readXMLFloat(configNode, "fist", floatValue)) voc->setSkillMultiplier(SKILL_FIST, floatValue); if(readXMLInteger(configNode, "fistBase", intValue)) voc->setSkillBase(SKILL_FIST, intValue); if(readXMLFloat(configNode, "club", floatValue)) voc->setSkillMultiplier(SKILL_CLUB, floatValue); if(readXMLInteger(configNode, "clubBase", intValue)) voc->setSkillBase(SKILL_CLUB, intValue); if(readXMLFloat(configNode, "axe", floatValue)) voc->setSkillMultiplier(SKILL_AXE, floatValue); if(readXMLInteger(configNode, "axeBase", intValue)) voc->setSkillBase(SKILL_AXE, intValue); if(readXMLFloat(configNode, "sword", floatValue)) voc->setSkillMultiplier(SKILL_SWORD, floatValue); if(readXMLInteger(configNode, "swordBase", intValue)) voc->setSkillBase(SKILL_SWORD, intValue); if(readXMLFloat(configNode, "distance", floatValue) || readXMLFloat(configNode, "dist", floatValue)) voc->setSkillMultiplier(SKILL_DIST, floatValue); if(readXMLInteger(configNode, "distanceBase", intValue) || readXMLInteger(configNode, "distBase", intValue)) voc->setSkillBase(SKILL_DIST, intValue); if(readXMLFloat(configNode, "shielding", floatValue) || readXMLFloat(configNode, "shield", floatValue)) voc->setSkillMultiplier(SKILL_SHIELD, floatValue); if(readXMLInteger(configNode, "shieldingBase", intValue) || readXMLInteger(configNode, "shieldBase", intValue)) voc->setSkillBase(SKILL_SHIELD, intValue); if(readXMLFloat(configNode, "fishing", floatValue) || readXMLFloat(configNode, "fish", floatValue)) voc->setSkillMultiplier(SKILL_FISH, floatValue); if(readXMLInteger(configNode, "fishingBase", intValue) || readXMLInteger(configNode, "fishBase", intValue)) voc->setSkillBase(SKILL_FISH, intValue); if(readXMLFloat(configNode, "experience", floatValue) || readXMLFloat(configNode, "exp", floatValue)) voc->setSkillMultiplier(SKILL__LEVEL, floatValue); if(readXMLInteger(configNode, "id", intValue)) { skills_t skill = (skills_t)intValue; if(intValue < SKILL_FIRST || intValue >= SKILL__LAST) { std::cout << "[Error - Vocations::parseVocationNode] No valid skill id (" << intValue << ")." << std::endl; continue; } if(readXMLInteger(configNode, "base", intValue)) voc->setSkillBase(skill, intValue); if(readXMLFloat(configNode, "multiplier", floatValue)) voc->setSkillMultiplier(skill, floatValue); } } else if(!xmlStrcmp(configNode->name, (const xmlChar*)"formula")) { if(readXMLFloat(configNode, "meleeDamage", floatValue)) voc->setMultiplier(MULTIPLIER_MELEE, floatValue); if(readXMLFloat(configNode, "distDamage", floatValue) || readXMLFloat(configNode, "distanceDamage", floatValue)) voc->setMultiplier(MULTIPLIER_DISTANCE, floatValue); if(readXMLFloat(configNode, "wandDamage", floatValue) || readXMLFloat(configNode, "rodDamage", floatValue)) voc->setMultiplier(MULTIPLIER_WAND, floatValue); if(readXMLFloat(configNode, "magDamage", floatValue) || readXMLFloat(configNode, "magicDamage", floatValue)) voc->setMultiplier(MULTIPLIER_MAGIC, floatValue); if(readXMLFloat(configNode, "magHealingDamage", floatValue) || readXMLFloat(configNode, "magicHealingDamage", floatValue)) voc->setMultiplier(MULTIPLIER_MAGICHEALING, floatValue); if(readXMLFloat(configNode, "defense", floatValue)) voc->setMultiplier(MULTIPLIER_DEFENSE, floatValue); if(readXMLFloat(configNode, "magDefense", floatValue) || readXMLFloat(configNode, "magicDefense", floatValue)) voc->setMultiplier(MULTIPLIER_MAGICDEFENSE, floatValue); if(readXMLFloat(configNode, "armor", floatValue)) voc->setMultiplier(MULTIPLIER_ARMOR, floatValue); } else if(!xmlStrcmp(configNode->name, (const xmlChar*)"absorb")) { if(readXMLInteger(configNode, "percentAll", intValue)) { for(uint32_t i = COMBAT_FIRST; i <= COMBAT_LAST; i++) voc->increaseAbsorbPercent((CombatType_t)i, intValue); } else if(readXMLInteger(configNode, "percentElements", intValue)) { voc->increaseAbsorbPercent(COMBAT_ENERGYDAMAGE, intValue); voc->increaseAbsorbPercent(COMBAT_FIREDAMAGE, intValue); voc->increaseAbsorbPercent(COMBAT_EARTHDAMAGE, intValue); voc->increaseAbsorbPercent(COMBAT_ICEDAMAGE, intValue); } else if(readXMLInteger(configNode, "percentMagic", intValue)) { voc->increaseAbsorbPercent(COMBAT_ENERGYDAMAGE, intValue); voc->increaseAbsorbPercent(COMBAT_FIREDAMAGE, intValue); voc->increaseAbsorbPercent(COMBAT_EARTHDAMAGE, intValue); voc->increaseAbsorbPercent(COMBAT_ICEDAMAGE, intValue); voc->increaseAbsorbPercent(COMBAT_HOLYDAMAGE, intValue); voc->increaseAbsorbPercent(COMBAT_DEATHDAMAGE, intValue); } else if(readXMLInteger(configNode, "percentEnergy", intValue)) voc->increaseAbsorbPercent(COMBAT_ENERGYDAMAGE, intValue); else if(readXMLInteger(configNode, "percentFire", intValue)) voc->increaseAbsorbPercent(COMBAT_FIREDAMAGE, intValue); else if(readXMLInteger(configNode, "percentPoison", intValue) || readXMLInteger(configNode, "percentEarth", intValue)) voc->increaseAbsorbPercent(COMBAT_EARTHDAMAGE, intValue); else if(readXMLInteger(configNode, "percentIce", intValue)) voc->increaseAbsorbPercent(COMBAT_ICEDAMAGE, intValue); else if(readXMLInteger(configNode, "percentHoly", intValue)) voc->increaseAbsorbPercent(COMBAT_HOLYDAMAGE, intValue); else if(readXMLInteger(configNode, "percentDeath", intValue)) voc->increaseAbsorbPercent(COMBAT_DEATHDAMAGE, intValue); else if(readXMLInteger(configNode, "percentLifeDrain", intValue)) voc->increaseAbsorbPercent(COMBAT_LIFEDRAIN, intValue); else if(readXMLInteger(configNode, "percentManaDrain", intValue)) voc->increaseAbsorbPercent(COMBAT_MANADRAIN, intValue); else if(readXMLInteger(configNode, "percentDrown", intValue)) voc->increaseAbsorbPercent(COMBAT_DROWNDAMAGE, intValue); else if(readXMLInteger(configNode, "percentPhysical", intValue)) voc->increaseAbsorbPercent(COMBAT_PHYSICALDAMAGE, intValue); else if(readXMLInteger(configNode, "percentHealing", intValue)) voc->increaseAbsorbPercent(COMBAT_HEALING, intValue); else if(readXMLInteger(configNode, "percentUndefined", intValue)) voc->increaseAbsorbPercent(COMBAT_UNDEFINEDDAMAGE, intValue); } configNode = configNode->next; } vocationsMap[voc->getId()] = voc; return true; }
bool parseVocationNode(xmlNodePtr vocationNode, VocationMap& vocationMap, StringVec& vocStringVec, std::string& errorStr) { if(xmlStrcmp(vocationNode->name,(const xmlChar*)"vocation")) return true; int32_t vocationId = -1; std::string strValue, tmpStrValue; if(readXMLString(vocationNode, "name", strValue)) { vocationId = Vocations::getInstance()->getVocationId(strValue); if(vocationId != -1) { vocationMap[vocationId] = true; int32_t promotedVocation = Vocations::getInstance()->getPromotedVocation(vocationId); if(promotedVocation != -1) vocationMap[promotedVocation] = true; } else { errorStr = "Wrong vocation name: " + strValue; return false; } } else if(readXMLString(vocationNode, "id", strValue)) { IntegerVec intVector; if(!parseIntegerVec(strValue, intVector)) { errorStr = "Invalid vocation id - '" + strValue + "'"; return false; } size_t size = intVector.size(); for(size_t i = 0; i < size; ++i) { Vocation* vocation = Vocations::getInstance()->getVocation(intVector[i]); if(vocation && vocation->getName() != "") { vocationId = vocation->getId(); strValue = vocation->getName(); vocationMap[vocationId] = true; int32_t promotedVocation = Vocations::getInstance()->getPromotedVocation(vocationId); if(promotedVocation != -1) vocationMap[promotedVocation] = true; } else { std::stringstream ss; ss << "Wrong vocation id: " << intVector[i]; errorStr = ss.str(); return false; } } } if(vocationId != -1 && (!readXMLString(vocationNode, "showInDescription", tmpStrValue) || booleanString(tmpStrValue))) vocStringVec.push_back(asLowerCaseString(strValue)); return true; }
void ValueCallback::getMinMaxValues(Player* player, int32_t& min, int32_t& max, bool useCharges) const { //"onGetPlayerMinMaxValues"(...) if(m_scriptInterface->reserveScriptEnv()){ ScriptEnviroment* env = m_scriptInterface->getScriptEnv(); lua_State* L = m_scriptInterface->getLuaState(); if(!env->setCallbackId(m_scriptId, m_scriptInterface)) return; uint32_t cid = env->addThing(player); m_scriptInterface->pushFunction(m_scriptId); lua_pushnumber(L, cid); int32_t parameters = 1; bool isMagicFormula = false; switch(type){ case FORMULA_LEVELMAGIC: { //"onGetPlayerMinMaxValues"(cid, level, maglevel) lua_pushnumber(L, player->getLevel()); lua_pushnumber(L, player->getMagicLevel()); parameters += 2; isMagicFormula = true; break; } case FORMULA_SKILL: { //"onGetPlayerMinMaxValues"(cid, attackSkill, attackValue, attackFactor) Item* tool = player->getWeapon(); int32_t attackSkill = player->getWeaponSkill(tool); int32_t attackValue = g_config.getNumber(ConfigManager::FIST_STRENGTH); if(tool){ attackValue = tool->getAttack(); if(useCharges && tool->hasCharges() && g_config.getNumber(ConfigManager::REMOVE_WEAPON_CHARGES)){ int32_t newCharge = std::max(0, tool->getCharges() - 1); g_game.transformItem(tool, tool->getID(), newCharge); } } float attackFactor = player->getAttackFactor(); lua_pushnumber(L, attackSkill); lua_pushnumber(L, attackValue); lua_pushnumber(L, attackFactor); parameters += 3; break; } default: std::cout << "ValueCallback::getMinMaxValues - unknown callback type" << std::endl; return; break; } int size0 = lua_gettop(L); if(lua_pcall(L, parameters, 2 /*nReturnValues*/, 0) != 0){ LuaScriptInterface::reportError(NULL, LuaScriptInterface::popString(L)); } else{ max = LuaScriptInterface::popNumber(L); min = LuaScriptInterface::popNumber(L); Vocation* vocation = player->getVocation(); if(isMagicFormula && vocation){ if(max > 0 && min > 0 && vocation->getHealingBaseDamage() != 1.0){ min = int32_t(min * vocation->getHealingBaseDamage()); max = int32_t(max * vocation->getHealingBaseDamage()); } else if(max < 0 && min < 0 && vocation->getMagicBaseDamage() != 1.0){ min = int32_t(min * vocation->getMagicBaseDamage()); max = int32_t(max * vocation->getMagicBaseDamage()); } } } if((lua_gettop(L) + parameters /*nParams*/ + 1) != size0){ LuaScriptInterface::reportError(NULL, "Stack size changed!"); } env->resetCallback(); m_scriptInterface->releaseScriptEnv(); } else{ std::cout << "[Error] Call stack overflow. ValueCallback::getMinMaxValues" << std::endl; return; } }
bool Combat::getMinMaxValues(Creature* creature, Creature* target, int32_t& min, int32_t& max) const { if(creature){ if(creature->getCombatValues(min, max)){ return true; } else if(Player* player = creature->getPlayer()){ if(params.valueCallback){ params.valueCallback->getMinMaxValues(player, min, max, params.useCharges); return true; } else{ switch(formulaType){ case FORMULA_LEVELMAGIC: { max = (int32_t)((player->getLevel() + player->getMagicLevel() * 4) * 1. * mina + minb); min = (int32_t)((player->getLevel() + player->getMagicLevel() * 4) * 1. * maxa + maxb); Vocation* vocation = player->getVocation(); if(vocation){ if(max > 0 && min > 0 && vocation->getHealingBaseDamage() != 1.0){ min = int32_t(min * vocation->getHealingBaseDamage()); max = int32_t(max * vocation->getHealingBaseDamage()); } else if(max < 0 && min < 0 && vocation->getMagicBaseDamage() != 1.0){ min = int32_t(min * vocation->getMagicBaseDamage()); max = int32_t(max * vocation->getMagicBaseDamage()); } } return true; break; } case FORMULA_SKILL: { Item* tool = player->getWeapon(); const Weapon* weapon = g_weapons->getWeapon(tool); min = (int32_t)minb; if(weapon){ max = (int32_t)(weapon->getWeaponDamage(player, target, tool, true) * maxa + maxb); if(params.useCharges && tool->hasCharges() && g_config.getNumber(ConfigManager::REMOVE_WEAPON_CHARGES)){ int32_t newCharge = std::max((int32_t)0, ((int32_t)tool->getCharges()) - 1); g_game.transformItem(tool, tool->getID(), newCharge); } } else{ max = (int32_t)maxb; } return true; break; } case FORMULA_VALUE: { min = (int32_t)mina; max = (int32_t)maxa; return true; break; } default: min = 0; max = 0; return false; break; } //std::cout << "No callback set for combat" << std::endl; } } } if(formulaType == FORMULA_VALUE){ min = (int32_t)mina; max = (int32_t)maxa; return true; } return false; }
bool Vocations::loadFromXml(const std::string& datadir) { std::string filename = datadir + "vocations.xml"; xmlDocPtr doc = xmlParseFile(filename.c_str()); if(doc){ xmlNodePtr root, p; root = xmlDocGetRootElement(doc); if(xmlStrcmp(root->name,(const xmlChar*)"vocations") != 0){ xmlFreeDoc(doc); return false; } p = root->children; while(p){ if(xmlStrcmp(p->name, (const xmlChar*)"vocation") == 0){ std::string str; int intVal; float floatVal; Vocation* voc = NULL; xmlNodePtr skillNode; if(readXMLInteger(p, "id", intVal)){ voc = new Vocation(intVal); if(readXMLString(p, "name", str)){ voc->name = str; } if(readXMLString(p, "description", str)){ voc->description = str; } if(readXMLInteger(p, "gaincap", intVal)){ voc->gainCap = intVal; } if(readXMLInteger(p, "gainhp", intVal)){ voc->gainHP = intVal; } if(readXMLInteger(p, "gainmana", intVal)){ voc->gainMana = intVal; } if(readXMLInteger(p, "gainhpticks", intVal)){ voc->gainHealthTicks = intVal; } if(readXMLInteger(p, "gainhpamount", intVal)){ voc->gainHealthAmount = intVal; } if(readXMLInteger(p, "gainmanaticks", intVal)){ voc->gainManaTicks = intVal; } if(readXMLInteger(p, "gainmanaamount", intVal)){ voc->gainManaAmount = intVal; } if(readXMLInteger(p, "maxsoul", intVal)){ voc->maxSoul = intVal; } if(readXMLInteger(p, "gainsoulticks", intVal)){ voc->gainSoulTicks = intVal; } if(readXMLFloat(p, "manamultiplier", floatVal)){ voc->manaMultiplier = floatVal; } skillNode = p->children; while(skillNode){ if(xmlStrcmp(skillNode->name, (const xmlChar*)"skill") == 0){ SkillType skill_id; try { if(readXMLInteger(skillNode, "id", intVal)){ skill_id = SkillType::fromInteger(intVal); } else if(readXMLString(skillNode, "name", str)){ skill_id = SkillType::fromString(str); } if(readXMLInteger(skillNode, "base", intVal)){ voc->skillBases[skill_id.value()] = intVal; } if(readXMLFloat(skillNode, "multiplier", floatVal)){ voc->skillMultipliers[skill_id.value()] = floatVal; } } catch(enum_conversion_error&){ std::cout << "Missing skill id ." << std::endl; } } else if(xmlStrcmp(skillNode->name, (const xmlChar*)"damage") == 0){ if(readXMLFloat(skillNode, "magicDamage", floatVal)){ voc->magicBaseDamage = floatVal; } if(readXMLFloat(skillNode, "wandDamage", floatVal)){ voc->wandBaseDamage = floatVal; } if(readXMLFloat(skillNode, "healingDamage", floatVal)){ voc->healingBaseDamage = floatVal; } } else if(xmlStrcmp(skillNode->name, (const xmlChar*)"meleeDamage") == 0){ if(readXMLFloat(skillNode, "sword", floatVal)){ voc->swordBaseDamage = floatVal; } if(readXMLFloat(skillNode, "axe", floatVal)){ voc->axeBaseDamage = floatVal; } if(readXMLFloat(skillNode, "club", floatVal)){ voc->clubBaseDamage = floatVal; } if(readXMLFloat(skillNode, "dist", floatVal)){ voc->distBaseDamage = floatVal; } if(readXMLFloat(skillNode, "fist", floatVal)){ voc->fistBaseDamage = floatVal; } } else if(xmlStrcmp(skillNode->name, (const xmlChar*)"defense") == 0){ if(readXMLFloat(skillNode, "baseDefense", floatVal)){ voc->baseDefense = floatVal; } if(readXMLFloat(skillNode, "armorDefense", floatVal)){ voc->armorDefense = floatVal; } } skillNode = skillNode->next; } //std::cout << "Voc id: " << voc_id << std::endl; //voc->debugVocation(); vocationsMap[voc->getID()] = voc; } else{ std::cout << "Missing vocation id." << std::endl; } } p = p->next; } xmlFreeDoc(doc); } return true; }