Postado Setembro 17, 2020 4 anos Diretor Em 17/09/2020 em 05:46, H3ITORR disse: ele fica em vermelho nessa linha //setCreatureName(cid, name, description) lua_register(m_luaState, "setCreatureName", LuaScriptInterface::luaSetCreatureName); int32_t LuaScriptInterface::luaSetCreatureName(lua_State* L) dai se eu coloco ali nos LuaScriptInterface para LuaInterface copila sereno mas o meu tfs 0.4 todos sao luaInterface se está dando erro então é pra ser assim int32_t LuaInterface::luaSetCreatureName(lua_State* L) lua_register(m_luaState, "setCreatureName", LuaInterface::luaSetCreatureName); Eu sou um entusiasta da programação apaixonado por ajudar a comunidade open source a crescer. Sempre em busca de novos desafios e oportunidades para contribuir com meu código. #OpenSource #Programação #Contribuição
Postado Setembro 17, 2020 4 anos ja coloquei assim L3K0T mas quando uso bunshin no jutsu com naruto ele cria o clone mas os clone nao usa o mesmo nick e tbm nao usa o buff!
Postado Setembro 17, 2020 4 anos Diretor Em 17/09/2020 em 05:50, H3ITORR disse: ja coloquei assim L3K0T mas quando uso bunshin no jutsu com naruto ele cria o clone mas os clone nao usa o mesmo nick e tbm nao usa o buff! local pos = {x = 10, y = 10, z = 7} local teste = doSummonCreature("Rat",pos) setCreatureName(pos, "Fake Rat", "a fake rat") ou local pos = {x = 10, y = 10, z = 7} local teste = doCreateMonster("Rat",pos) setCreatureName(pos, "Fake Rat", "a fake rat") já tentou assim?? tbm tente recompilar no modo Rebuilder Eu sou um entusiasta da programação apaixonado por ajudar a comunidade open source a crescer. Sempre em busca de novos desafios e oportunidades para contribuir com meu código. #OpenSource #Programação #Contribuição
Postado Março 21, 2021 4 anos minhas sources não tem: Monster::Monster(MonsterType* _mType): Creature() { isIdle = true; isMasterInRange = false; teleportToMaster = false; mType = _mType; spawn = NULL; raid = NULL; name = mType->name; nameDescription = mType->nameDescription; oq eu faço ? monster.cpp: Mostrar conteúdo oculto //////////////////////////////////////////////////////////////////////// // OpenTibia - an opensource roleplaying game //////////////////////////////////////////////////////////////////////// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. //////////////////////////////////////////////////////////////////////// #include "otpch.h" #include <libxml/xmlmemory.h> #include <libxml/parser.h> #include "monsters.h" #include "tools.h" #include "monster.h" #include "luascript.h" #include "container.h" #include "weapons.h" #include "spells.h" #include "combat.h" #include "configmanager.h" #include "game.h" extern Game g_game; extern Spells* g_spells; extern Monsters g_monsters; extern ConfigManager g_config; void MonsterType::reset() { canPushItems = canPushCreatures = isSummonable = isIllusionable = isConvinceable = isLureable = isWalkable = hideName = hideHealth = false; pushable = isAttackable = isHostile = true; outfit.lookHead = outfit.lookBody = outfit.lookLegs = outfit.lookFeet = outfit.lookType = outfit.lookTypeEx = outfit.lookAddons = 0; runAwayHealth = manaCost = lightLevel = lightColor = yellSpeedTicks = yellChance = changeTargetSpeed = changeTargetChance = 0; experience = defense = armor = lookCorpse = corpseUnique = corpseAction = conditionImmunities = damageImmunities = 0; maxSummons = -1; targetDistance = 1; staticAttackChance = 95; health = healthMax = 100; baseSpeed = 200; race = RACE_BLOOD; skull = SKULL_NONE; partyShield = SHIELD_NONE; guildEmblem = EMBLEM_NONE; lootMessage = LOOTMSG_IGNORE; for(SpellList::iterator it = spellAttackList.begin(); it != spellAttackList.end(); ++it) { if(!it->combatSpell) continue; delete it->spell; it->spell = NULL; } spellAttackList.clear(); for(SpellList::iterator it = spellDefenseList.begin(); it != spellDefenseList.end(); ++it) { if(!it->combatSpell) continue; delete it->spell; it->spell = NULL; } spellDefenseList.clear(); summonList.clear(); scriptList.clear(); voiceVector.clear(); lootItems.clear(); elementMap.clear(); } uint16_t Monsters::getLootRandom() { return (uint16_t)std::ceil((double)random_range(0, MAX_LOOTCHANCE) / g_config.getDouble(ConfigManager::RATE_LOOT)); } void MonsterType::dropLoot(Container* corpse) { Item* tmpItem = NULL; for(LootItems::const_iterator it = lootItems.begin(); it != lootItems.end() && !corpse->full(); ++it) { if((tmpItem = createLoot(*it))) { if(Container* container = tmpItem->getContainer()) { if(createChildLoot(container, (*it))) corpse->__internalAddThing(tmpItem); else delete container; } else corpse->__internalAddThing(tmpItem); } } corpse->__startDecaying(); uint32_t ownerId = corpse->getCorpseOwner(); if(!ownerId) return; Player* owner = g_game.getPlayerByGuid(ownerId); if(!owner) return; LootMessage_t message = lootMessage; if(message == LOOTMSG_IGNORE) message = (LootMessage_t)g_config.getNumber(ConfigManager::LOOT_MESSAGE); if(message < LOOTMSG_PLAYER) return; std::stringstream ss; ss << "Loot of " << nameDescription << ": " << corpse->getContentDescription() << "."; if(owner->getParty() && message > LOOTMSG_PLAYER) owner->getParty()->broadcastMessage((MessageClasses)g_config.getNumber(ConfigManager::LOOT_MESSAGE_TYPE), ss.str()); else if(message == LOOTMSG_PLAYER || message == LOOTMSG_BOTH) owner->sendTextMessage((MessageClasses)g_config.getNumber(ConfigManager::LOOT_MESSAGE_TYPE), ss.str()); } Item* MonsterType::createLoot(const LootBlock& lootBlock) { uint16_t item = lootBlock.ids[0], random = Monsters::getLootRandom(); if(lootBlock.ids.size() > 1) item = lootBlock.ids[random_range((size_t)0, lootBlock.ids.size() - 1)]; Item* tmpItem = NULL; if(Item::items[item].stackable) { if(random < lootBlock.chance) tmpItem = Item::CreateItem(item, (random % lootBlock.count + 1)); } else if(random < lootBlock.chance) tmpItem = Item::CreateItem(item, 0); if(!tmpItem) return NULL; if(lootBlock.subType != -1) tmpItem->setSubType(lootBlock.subType); if(lootBlock.actionId != -1) tmpItem->setActionId(lootBlock.actionId, false); if(lootBlock.uniqueId != -1) tmpItem->setUniqueId(lootBlock.uniqueId); if(!lootBlock.text.empty()) tmpItem->setText(lootBlock.text); return tmpItem; } bool MonsterType::createChildLoot(Container* parent, const LootBlock& lootBlock) { LootItems::const_iterator it = lootBlock.childLoot.begin(); if(it == lootBlock.childLoot.end()) return true; Item* tmpItem = NULL; for(; it != lootBlock.childLoot.end() && !parent->full(); ++it) { if((tmpItem = createLoot(*it))) { if(Container* container = tmpItem->getContainer()) { if(createChildLoot(container, (*it))) parent->__internalAddThing(container); else delete container; } else parent->__internalAddThing(tmpItem); } } return !parent->empty(); } bool Monsters::loadFromXml(bool reloading /*= false*/) { loaded = false; xmlDocPtr doc = xmlParseFile(getFilePath(FILE_TYPE_OTHER, "monster/monsters.xml").c_str()); if(!doc) { std::clog << "[Warning - Monsters::loadFromXml] Cannot load monsters file." << std::endl; std::clog << getLastXMLError() << std::endl; return false; } xmlNodePtr p, root = xmlDocGetRootElement(doc); if(xmlStrcmp(root->name,(const xmlChar*)"monsters")) { std::clog << "[Error - Monsters::loadFromXml] Malformed monsters file." << std::endl; xmlFreeDoc(doc); return false; } p = root->children; while(p) { if(p->type != XML_ELEMENT_NODE) { p = p->next; continue; } if(xmlStrcmp(p->name, (const xmlChar*)"monster")) { std::clog << "[Warning - Monsters::loadFromXml] Unknown node name (" << p->name << ")." << std::endl; p = p->next; continue; } std::string file, name; if(readXMLString(p, "file", file) && readXMLString(p, "name", name)) { file = getFilePath(FILE_TYPE_OTHER, "monster/" + file); loadMonster(file, name, reloading); } p = p->next; } xmlFreeDoc(doc); loaded = true; return loaded; } ConditionDamage* Monsters::getDamageCondition(ConditionType_t conditionType, int32_t maxDamage, int32_t minDamage, int32_t startDamage, uint32_t tickInterval) { if(ConditionDamage* condition = dynamic_cast<ConditionDamage*>(Condition::createCondition(CONDITIONID_COMBAT, conditionType, 0))) { condition->setParam(CONDITIONPARAM_TICKINTERVAL, tickInterval); condition->setParam(CONDITIONPARAM_MINVALUE, minDamage); condition->setParam(CONDITIONPARAM_MAXVALUE, maxDamage); condition->setParam(CONDITIONPARAM_STARTVALUE, startDamage); condition->setParam(CONDITIONPARAM_DELAYED, 1); return condition; } return NULL; } bool Monsters::deserializeSpell(xmlNodePtr node, spellBlock_t& sb, const std::string& description) { sb.range = sb.minCombatValue = sb.maxCombatValue = 0; sb.combatSpell = sb.isMelee = false; sb.chance = 100; sb.speed = 2000; std::string name, scriptName; bool isScripted = false; if(readXMLString(node, "script", scriptName)) isScripted = true; else if(!readXMLString(node, "name", name)) return false; int32_t intValue; std::string strValue; if(readXMLInteger(node, "speed", intValue) || readXMLInteger(node, "interval", intValue)) sb.speed = std::max(1, intValue); if(readXMLInteger(node, "chance", intValue)) { if(intValue < 0 || intValue > 100) intValue = 100; sb.chance = intValue; } if(readXMLInteger(node, "range", intValue)) { if(intValue < 0) intValue = 0; if(intValue > Map::maxViewportX * 2) intValue = Map::maxViewportX * 2; sb.range = intValue; } if(readXMLInteger(node, "min", intValue)) sb.minCombatValue = intValue; if(readXMLInteger(node, "max", intValue)) sb.maxCombatValue = intValue; //normalize values if(std::abs(sb.minCombatValue) > std::abs(sb.maxCombatValue)) std::swap(sb.minCombatValue, sb.maxCombatValue); if((sb.spell = g_spells->getSpellByName(name))) return true; CombatSpell* combatSpell = NULL; bool needTarget = false, needDirection = false; if(isScripted) { if(readXMLString(node, "direction", strValue)) needDirection = booleanString(strValue); if(readXMLString(node, "target", strValue)) needTarget = booleanString(strValue); combatSpell = new CombatSpell(NULL, needTarget, needDirection); if(!combatSpell->loadScript(getFilePath(FILE_TYPE_OTHER, g_spells->getScriptBaseName() + "/scripts/" + scriptName), true)) { delete combatSpell; return false; } if(!combatSpell->loadScriptCombat()) { delete combatSpell; return false; } combatSpell->getCombat()->setPlayerCombatValues(FORMULA_VALUE, sb.minCombatValue, 0, sb.maxCombatValue, 0, 0, 0, 0, 0, 0, 0); } else { Combat* combat = new Combat; sb.combatSpell = true; if(readXMLInteger(node, "length", intValue)) { int32_t length = intValue; if(length > 0) { int32_t spread = 3; //need direction spell if(readXMLInteger(node, "spread", intValue)) spread = std::max(0, intValue); CombatArea* area = new CombatArea(); area->setupArea(length, spread); combat->setArea(area); needDirection = true; } } if(readXMLInteger(node, "radius", intValue)) { int32_t radius = intValue; //target spell if(readXMLInteger(node, "target", intValue)) needTarget = (intValue != 0); CombatArea* area = new CombatArea(); area->setupArea(radius); combat->setArea(area); } std::string tmpName = asLowerCaseString(name); if(tmpName == "melee" || tmpName == "distance") { int32_t attack = 0, skill = 0; if(readXMLInteger(node, "attack", attack) && readXMLInteger(node, "skill", skill)) { sb.minCombatValue = 0; sb.maxCombatValue = -Weapons::getMaxMeleeDamage(skill, attack); } uint32_t tickInterval = 10000; ConditionType_t conditionType = CONDITION_NONE; if(readXMLInteger(node, "physical", intValue)) conditionType = CONDITION_PHYSICAL; else if(readXMLInteger(node, "fire", intValue)) conditionType = CONDITION_FIRE; else if(readXMLInteger(node, "energy", intValue)) conditionType = CONDITION_ENERGY; else if(readXMLInteger(node, "earth", intValue)) conditionType = CONDITION_POISON; else if(readXMLInteger(node, "freeze", intValue)) conditionType = CONDITION_FREEZING; else if(readXMLInteger(node, "dazzle", intValue)) conditionType = CONDITION_DAZZLED; else if(readXMLInteger(node, "curse", intValue)) conditionType = CONDITION_CURSED; else if(readXMLInteger(node, "drown", intValue)) { conditionType = CONDITION_DROWN; tickInterval = 5000; } else if(readXMLInteger(node, "poison", intValue)) { conditionType = CONDITION_POISON; tickInterval = 5000; } uint32_t damage = std::abs(intValue); if(readXMLInteger(node, "tick", intValue) && intValue > 0) tickInterval = intValue; if(conditionType != CONDITION_NONE) { Condition* condition = getDamageCondition(conditionType, damage, damage, 0, tickInterval); if(condition) combat->setCondition(condition); } sb.isMelee = true; sb.range = 1; combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_PHYSICALDAMAGE); combat->setParam(COMBATPARAM_BLOCKEDBYSHIELD, 1); combat->setParam(COMBATPARAM_BLOCKEDBYARMOR, 1); } else if(tmpName == "physical") { combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_PHYSICALDAMAGE); combat->setParam(COMBATPARAM_BLOCKEDBYARMOR, 1); } else if(tmpName == "drown") combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_DROWNDAMAGE); else if(tmpName == "fire") combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_FIREDAMAGE); else if(tmpName == "energy") combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_ENERGYDAMAGE); else if(tmpName == "poison" || tmpName == "earth") combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_EARTHDAMAGE); else if(tmpName == "ice") combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_ICEDAMAGE); else if(tmpName == "holy") combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_HOLYDAMAGE); else if(tmpName == "death") combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_DEATHDAMAGE); else if(tmpName == "lifedrain") combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_LIFEDRAIN); else if(tmpName == "manadrain") combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_MANADRAIN); else if(tmpName == "healing") { bool aggressive = false; if(readXMLInteger(node, "self", intValue)) aggressive = intValue; combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_HEALING); combat->setParam(COMBATPARAM_AGGRESSIVE, aggressive); } else if(tmpName == "undefined") combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_UNDEFINEDDAMAGE); else if(tmpName == "speed") { int32_t speedChange = 0, duration = 10000; if(readXMLInteger(node, "duration", intValue)) duration = intValue; enum Aggressive { NO, YES, AUTO } aggressive = AUTO; if(readXMLInteger(node, "self", intValue)) aggressive = (Aggressive)intValue; if(readXMLInteger(node, "speedchange", intValue)) speedChange = std::max(-1000, intValue); //cant be slower than 100% std::vector<Outfit_t> outfits; for(xmlNodePtr tmpNode = node->children; tmpNode; tmpNode = tmpNode->next) { if(xmlStrcmp(tmpNode->name,(const xmlChar*)"outfit")) continue; if(readXMLInteger(tmpNode, "type", intValue)) { Outfit_t outfit; outfit.lookType = intValue; if(readXMLInteger(tmpNode, "head", intValue)) outfit.lookHead = intValue; if(readXMLInteger(tmpNode, "body", intValue)) outfit.lookBody = intValue; if(readXMLInteger(tmpNode, "legs", intValue)) outfit.lookLegs = intValue; if(readXMLInteger(tmpNode, "feet", intValue)) outfit.lookFeet = intValue; if(readXMLInteger(tmpNode, "addons", intValue)) outfit.lookAddons = intValue; outfits.push_back(outfit); } if(readXMLInteger(tmpNode, "typeex", intValue) || readXMLInteger(tmpNode, "item", intValue)) { Outfit_t outfit; outfit.lookTypeEx = intValue; outfits.push_back(outfit); } if(readXMLString(tmpNode, "monster", strValue)) { if(MonsterType* mType = g_monsters.getMonsterType(strValue)) outfits.push_back(mType->outfit); } } ConditionType_t conditionType = CONDITION_PARALYZE; if(speedChange > 0) { conditionType = CONDITION_HASTE; if(aggressive == AUTO) aggressive = NO; } else if(aggressive == AUTO) aggressive = YES; if(ConditionSpeed* condition = dynamic_cast<ConditionSpeed*>(Condition::createCondition( CONDITIONID_COMBAT, conditionType, duration))) { condition->setFormulaVars((speedChange / 1000.), 0, (speedChange / 1000.), 0); if(!outfits.empty()) condition->setOutfits(outfits); combat->setCondition(condition); combat->setParam(COMBATPARAM_AGGRESSIVE, aggressive); } } else if(tmpName == "outfit") { std::vector<Outfit_t> outfits; for(xmlNodePtr tmpNode = node->children; tmpNode; tmpNode = tmpNode->next) { if(xmlStrcmp(tmpNode->name,(const xmlChar*)"outfit")) continue; if(readXMLInteger(tmpNode, "type", intValue)) { Outfit_t outfit; outfit.lookType = intValue; if(readXMLInteger(tmpNode, "head", intValue)) outfit.lookHead = intValue; if(readXMLInteger(tmpNode, "body", intValue)) outfit.lookBody = intValue; if(readXMLInteger(tmpNode, "legs", intValue)) outfit.lookLegs = intValue; if(readXMLInteger(tmpNode, "feet", intValue)) outfit.lookFeet = intValue; if(readXMLInteger(tmpNode, "addons", intValue)) outfit.lookAddons = intValue; outfits.push_back(outfit); } if(readXMLInteger(tmpNode, "typeex", intValue) || readXMLInteger(tmpNode, "item", intValue)) { Outfit_t outfit; outfit.lookTypeEx = intValue; outfits.push_back(outfit); } if(readXMLString(tmpNode, "monster", strValue)) { if(MonsterType* mType = g_monsters.getMonsterType(strValue)) outfits.push_back(mType->outfit); } } if(outfits.empty()) { if(readXMLInteger(node, "type", intValue)) { Outfit_t outfit; outfit.lookType = intValue; if(readXMLInteger(node, "head", intValue)) outfit.lookHead = intValue; if(readXMLInteger(node, "body", intValue)) outfit.lookBody = intValue; if(readXMLInteger(node, "legs", intValue)) outfit.lookLegs = intValue; if(readXMLInteger(node, "feet", intValue)) outfit.lookFeet = intValue; if(readXMLInteger(node, "addons", intValue)) outfit.lookAddons = intValue; outfits.push_back(outfit); } if(readXMLInteger(node, "typeex", intValue) || readXMLInteger(node, "item", intValue)) { Outfit_t outfit; outfit.lookTypeEx = intValue; outfits.push_back(outfit); } if(readXMLString(node, "monster", strValue)) { if(MonsterType* mType = g_monsters.getMonsterType(strValue)) outfits.push_back(mType->outfit); } } if(!outfits.empty()) { int32_t duration = 10000; if(readXMLInteger(node, "duration", intValue)) duration = intValue; bool aggressive = false; if(readXMLInteger(node, "self", intValue)) aggressive = intValue; if(ConditionOutfit* condition = dynamic_cast<ConditionOutfit*>(Condition::createCondition( CONDITIONID_COMBAT, CONDITION_OUTFIT, duration))) { condition->setOutfits(outfits); combat->setCondition(condition); combat->setParam(COMBATPARAM_AGGRESSIVE, aggressive); } } } else if(tmpName == "invisible") { int32_t duration = 10000; if(readXMLInteger(node, "duration", intValue)) duration = intValue; bool aggressive = false; if(readXMLInteger(node, "self", intValue)) aggressive = intValue; if(Condition* condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_INVISIBLE, duration)) { combat->setParam(COMBATPARAM_AGGRESSIVE, aggressive); combat->setCondition(condition); } } else if(tmpName == "drunk") { int32_t duration = 10000; if(readXMLInteger(node, "duration", intValue)) duration = intValue; if(Condition* condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_DRUNK, duration)) combat->setCondition(condition); } else if(tmpName == "skills" || tmpName == "attributes") { uint32_t duration = 10000, subId = 0; if(readXMLInteger(node, "duration", intValue)) duration = intValue; if(readXMLInteger(node, "subid", intValue)) subId = intValue; intValue = 0; ConditionParam_t param = CONDITIONPARAM_BUFF; //to know was it loaded if(readXMLInteger(node, "melee", intValue)) param = CONDITIONPARAM_SKILL_MELEE; else if(readXMLInteger(node, "fist", intValue)) param = CONDITIONPARAM_SKILL_FIST; else if(readXMLInteger(node, "club", intValue)) param = CONDITIONPARAM_SKILL_CLUB; else if(readXMLInteger(node, "axe", intValue)) param = CONDITIONPARAM_SKILL_AXE; else if(readXMLInteger(node, "sword", intValue)) param = CONDITIONPARAM_SKILL_SWORD; else if(readXMLInteger(node, "distance", intValue) || readXMLInteger(node, "dist", intValue)) param = CONDITIONPARAM_SKILL_DISTANCE; else if(readXMLInteger(node, "shielding", intValue) || readXMLInteger(node, "shield", intValue)) param = CONDITIONPARAM_SKILL_SHIELD; else if(readXMLInteger(node, "fishing", intValue) || readXMLInteger(node, "fish", intValue)) param = CONDITIONPARAM_SKILL_FISHING; else if(readXMLInteger(node, "meleePercent", intValue)) param = CONDITIONPARAM_SKILL_MELEEPERCENT; else if(readXMLInteger(node, "fistPercent", intValue)) param = CONDITIONPARAM_SKILL_FISTPERCENT; else if(readXMLInteger(node, "clubPercent", intValue)) param = CONDITIONPARAM_SKILL_CLUBPERCENT; else if(readXMLInteger(node, "axePercent", intValue)) param = CONDITIONPARAM_SKILL_AXEPERCENT; else if(readXMLInteger(node, "swordPercent", intValue)) param = CONDITIONPARAM_SKILL_SWORDPERCENT; else if(readXMLInteger(node, "distancePercent", intValue) || readXMLInteger(node, "distPercent", intValue)) param = CONDITIONPARAM_SKILL_DISTANCEPERCENT; else if(readXMLInteger(node, "shieldingPercent", intValue) || readXMLInteger(node, "shieldPercent", intValue)) param = CONDITIONPARAM_SKILL_SHIELDPERCENT; else if(readXMLInteger(node, "fishingPercent", intValue) || readXMLInteger(node, "fishPercent", intValue)) param = CONDITIONPARAM_SKILL_FISHINGPERCENT; else if(readXMLInteger(node, "maxhealth", intValue)) param = CONDITIONPARAM_STAT_MAXHEALTHPERCENT; else if(readXMLInteger(node, "maxmana", intValue)) param = CONDITIONPARAM_STAT_MAXMANAPERCENT; else if(readXMLInteger(node, "soul", intValue)) param = CONDITIONPARAM_STAT_SOULPERCENT; else if(readXMLInteger(node, "magiclevel", intValue) || readXMLInteger(node, "maglevel", intValue)) param = CONDITIONPARAM_STAT_MAGICLEVELPERCENT; else if(readXMLInteger(node, "maxhealthPercent", intValue)) param = CONDITIONPARAM_STAT_MAXHEALTHPERCENT; else if(readXMLInteger(node, "maxmanaPercent", intValue)) param = CONDITIONPARAM_STAT_MAXMANAPERCENT; else if(readXMLInteger(node, "soulPercent", intValue)) param = CONDITIONPARAM_STAT_SOULPERCENT; else if(readXMLInteger(node, "magiclevelPercent", intValue) || readXMLInteger(node, "maglevelPercent", intValue)) param = CONDITIONPARAM_STAT_MAGICLEVELPERCENT; if(param != CONDITIONPARAM_BUFF) { if(ConditionAttributes* condition = dynamic_cast<ConditionAttributes*>(Condition::createCondition( CONDITIONID_COMBAT, CONDITION_ATTRIBUTES, duration, false, subId))) { condition->setParam(param, intValue); combat->setCondition(condition); } } } else if(tmpName == "firefield") combat->setParam(COMBATPARAM_CREATEITEM, 1492); else if(tmpName == "poisonfield") combat->setParam(COMBATPARAM_CREATEITEM, 1496); else if(tmpName == "energyfield") combat->setParam(COMBATPARAM_CREATEITEM, 1495); else if(tmpName == "firecondition" || tmpName == "energycondition" || tmpName == "drowncondition" || tmpName == "poisoncondition" || tmpName == "earthcondition" || tmpName == "freezecondition" || tmpName == "cursecondition" || tmpName == "dazzlecondition") { ConditionType_t conditionType = CONDITION_NONE; uint32_t tickInterval = 2000; if(tmpName == "physicalcondition") { conditionType = CONDITION_PHYSICAL; tickInterval = 5000; } else if(tmpName == "firecondition") { conditionType = CONDITION_FIRE; tickInterval = 10000; } else if(tmpName == "energycondition") { conditionType = CONDITION_ENERGY; tickInterval = 10000; } else if(tmpName == "earthcondition") { conditionType = CONDITION_POISON; tickInterval = 10000; } else if(tmpName == "freezecondition") { conditionType = CONDITION_FREEZING; tickInterval = 10000; } else if(tmpName == "cursecondition") { conditionType = CONDITION_CURSED; tickInterval = 10000; } else if(tmpName == "dazzlecondition") { conditionType = CONDITION_DAZZLED; tickInterval = 10000; } else if(tmpName == "drowncondition") { conditionType = CONDITION_DROWN; tickInterval = 5000; } else if(tmpName == "poisoncondition") { conditionType = CONDITION_POISON; tickInterval = 5000; } if(readXMLInteger(node, "tick", intValue) && intValue > 0) tickInterval = intValue; int32_t startDamage = 0, minDamage = std::abs(sb.minCombatValue), maxDamage = std::abs(sb.maxCombatValue); if(readXMLInteger(node, "start", intValue)) startDamage = std::max(std::abs(intValue), minDamage); if(Condition* condition = getDamageCondition(conditionType, maxDamage, minDamage, startDamage, tickInterval)) combat->setCondition(condition); } else if(tmpName == "strength") { //TODO: monster extra strength } else if(tmpName == "effect") {/*show some effect and bye bye!*/} else { delete combat; std::clog << "[Error - Monsters::deserializeSpell] " << description << " - Unknown spell name: " << name << std::endl; return false; } combat->setPlayerCombatValues(FORMULA_VALUE, sb.minCombatValue, 0, sb.maxCombatValue, 0, 0, 0, 0, 0, 0, 0); combatSpell = new CombatSpell(combat, needTarget, needDirection); xmlNodePtr attributeNode = node->children; while(attributeNode) { if(!xmlStrcmp(attributeNode->name, (const xmlChar*)"attribute")) { if(readXMLString(attributeNode, "key", strValue)) { std::string tmpStrValue = asLowerCaseString(strValue); if(tmpStrValue == "shooteffect") { if(readXMLString(attributeNode, "value", strValue)) { ShootEffect_t shoot = getShootType(strValue); if(shoot != SHOOT_EFFECT_UNKNOWN) combat->setParam(COMBATPARAM_DISTANCEEFFECT, shoot); else std::clog << "[Warning - Monsters::deserializeSpell] " << description << " - Unknown shootEffect: " << strValue << std::endl; } } else if(tmpStrValue == "areaeffect") { if(readXMLString(attributeNode, "value", strValue)) { MagicEffect_t effect = getMagicEffect(strValue); if(effect != MAGIC_EFFECT_UNKNOWN) combat->setParam(COMBATPARAM_EFFECT, effect); else std::clog << "[Warning - Monsters::deserializeSpell] " << description << " - Unknown areaEffect: " << strValue << std::endl; } } else std::clog << "[Warning - Monsters::deserializeSpells] Effect type \"" << strValue << "\" does not exist." << std::endl; } } attributeNode = attributeNode->next; } } sb.spell = combatSpell; return true; } #define SHOW_XML_WARNING(desc) std::clog << "[Warning - Monsters::loadMonster] " << desc << ". (" << file << ")" << std::endl; #define SHOW_XML_ERROR(desc) std::clog << "[Error - Monsters::loadMonster] " << desc << ". (" << file << ")" << std::endl; bool Monsters::loadMonster(const std::string& file, const std::string& monsterName, bool reloading/* = false*/) { if(getIdByName(monsterName) && !reloading) { std::clog << "[Warning - Monsters::loadMonster] Duplicate registered monster with name: " << monsterName << std::endl; return true; } bool monsterLoad, new_mType = true; MonsterType* mType = NULL; if(reloading) { uint32_t id = getIdByName(monsterName); if(id != 0) { mType = getMonsterType(id); if(mType != NULL) { new_mType = false; mType->reset(); } } } if(new_mType) mType = new MonsterType(); xmlDocPtr doc = xmlParseFile(file.c_str()); if(!doc) { std::clog << "[Warning - Monsters::loadMonster] Cannot load monster (" << monsterName << ") file (" << file << ")." << std::endl; std::clog << getLastXMLError() << std::endl; return false; } monsterLoad = true; xmlNodePtr p, root = xmlDocGetRootElement(doc); if(xmlStrcmp(root->name,(const xmlChar*)"monster")) { std::clog << "[Error - Monsters::loadMonster] Malformed monster (" << monsterName << ") file (" << file << ")." << std::endl; xmlFreeDoc(doc); return false; } int32_t intValue; std::string strValue; if(readXMLString(root, "name", strValue)) mType->name = strValue; else monsterLoad = false; if(readXMLString(root, "nameDescription", strValue)) mType->nameDescription = strValue; else { mType->nameDescription = "a " + mType->name; toLowerCaseString(mType->nameDescription); } if(readXMLString(root, "race", strValue)) { std::string tmpStrValue = asLowerCaseString(strValue); if(tmpStrValue == "venom" || atoi(strValue.c_str()) == 1) mType->race = RACE_VENOM; else if(tmpStrValue == "blood" || atoi(strValue.c_str()) == 2) mType->race = RACE_BLOOD; else if(tmpStrValue == "undead" || atoi(strValue.c_str()) == 3) mType->race = RACE_UNDEAD; else if(tmpStrValue == "fire" || atoi(strValue.c_str()) == 4) mType->race = RACE_FIRE; else if(tmpStrValue == "energy" || atoi(strValue.c_str()) == 5) mType->race = RACE_ENERGY; else SHOW_XML_WARNING("Unknown race type " << strValue); } if(readXMLInteger(root, "experience", intValue)) mType->experience = intValue; if(readXMLInteger(root, "speed", intValue)) mType->baseSpeed = intValue; if(readXMLInteger(root, "manacost", intValue)) mType->manaCost = intValue; if(readXMLString(root, "skull", strValue)) mType->skull = getSkulls(strValue); if(readXMLString(root, "shield", strValue)) mType->partyShield = getShields(strValue); if(readXMLString(root, "emblem", strValue)) mType->guildEmblem = getEmblems(strValue); p = root->children; while(p && monsterLoad) { if(p->type != XML_ELEMENT_NODE) { p = p->next; continue; } if(!xmlStrcmp(p->name, (const xmlChar*)"health")) { if(readXMLInteger(p, "now", intValue)) mType->health = intValue; else { SHOW_XML_ERROR("Missing health.now"); monsterLoad = false; } if(readXMLInteger(p, "max", intValue)) mType->healthMax = intValue; else { SHOW_XML_ERROR("Missing health.max"); monsterLoad = false; } } else if(!xmlStrcmp(p->name, (const xmlChar*)"flags")) { xmlNodePtr tmpNode = p->children; while(tmpNode) { if(xmlStrcmp(tmpNode->name, (const xmlChar*)"flag") == 0) { if(readXMLString(tmpNode, "summonable", strValue)) mType->isSummonable = booleanString(strValue); if(readXMLString(tmpNode, "attackable", strValue)) mType->isAttackable = booleanString(strValue); if(readXMLString(tmpNode, "hostile", strValue)) mType->isHostile = booleanString(strValue); if(readXMLString(tmpNode, "illusionable", strValue)) mType->isIllusionable = booleanString(strValue); if(readXMLString(tmpNode, "convinceable", strValue)) mType->isConvinceable = booleanString(strValue); if(readXMLString(tmpNode, "pushable", strValue)) mType->pushable = booleanString(strValue); if(readXMLString(tmpNode, "canpushitems", strValue)) mType->canPushItems = booleanString(strValue); if(readXMLString(tmpNode, "canpushcreatures", strValue)) mType->canPushCreatures = booleanString(strValue); if(readXMLString(tmpNode, "hidename", strValue)) mType->hideName = booleanString(strValue); if(readXMLString(tmpNode, "hidehealth", strValue)) mType->hideHealth = booleanString(strValue); if(readXMLInteger(tmpNode, "lootmessage", intValue)) mType->lootMessage = (LootMessage_t)intValue; if(readXMLInteger(tmpNode, "staticattack", intValue)) { if(intValue < 0 || intValue > 100) { SHOW_XML_WARNING("staticattack lower than 0 or greater than 100"); intValue = 0; } mType->staticAttackChance = intValue; } if(readXMLInteger(tmpNode, "lightlevel", intValue)) mType->lightLevel = intValue; if(readXMLInteger(tmpNode, "lightcolor", intValue)) mType->lightColor = intValue; if(readXMLInteger(tmpNode, "targetdistance", intValue)) { if(intValue > Map::maxViewportX) SHOW_XML_WARNING("targetdistance greater than maxViewportX"); mType->targetDistance = std::max(1, intValue); } if(readXMLInteger(tmpNode, "runonhealth", intValue)) mType->runAwayHealth = intValue; if(readXMLString(tmpNode, "lureable", strValue)) mType->isLureable = booleanString(strValue); if(readXMLString(tmpNode, "walkable", strValue)) mType->isWalkable = booleanString(strValue); if(readXMLString(tmpNode, "skull", strValue)) mType->skull = getSkulls(strValue); if(readXMLString(tmpNode, "shield", strValue)) mType->partyShield = getShields(strValue); if(readXMLString(tmpNode, "emblem", strValue)) mType->guildEmblem = getEmblems(strValue); } tmpNode = tmpNode->next; } //if a monster can push creatures, it should not be pushable if(mType->canPushCreatures && mType->pushable) mType->pushable = false; } else if(!xmlStrcmp(p->name, (const xmlChar*)"targetchange")) { if(readXMLInteger(p, "speed", intValue) || readXMLInteger(p, "interval", intValue)) mType->changeTargetSpeed = std::max(1, intValue); else SHOW_XML_WARNING("Missing targetchange.speed"); if(readXMLInteger(p, "chance", intValue)) mType->changeTargetChance = intValue; else SHOW_XML_WARNING("Missing targetchange.chance"); } else if(!xmlStrcmp(p->name, (const xmlChar*)"strategy")) { if(readXMLInteger(p, "attack", intValue)) {} //mType->attackStrength = intValue; if(readXMLInteger(p, "defense", intValue)) {} //mType->defenseStrength = intValue; } else if(!xmlStrcmp(p->name, (const xmlChar*)"look")) { if(readXMLInteger(p, "type", intValue)) { mType->outfit.lookType = intValue; if(readXMLInteger(p, "head", intValue)) mType->outfit.lookHead = intValue; if(readXMLInteger(p, "body", intValue)) mType->outfit.lookBody = intValue; if(readXMLInteger(p, "legs", intValue)) mType->outfit.lookLegs = intValue; if(readXMLInteger(p, "feet", intValue)) mType->outfit.lookFeet = intValue; if(readXMLInteger(p, "addons", intValue)) mType->outfit.lookAddons = intValue; } else if(readXMLInteger(p, "typeex", intValue)) mType->outfit.lookTypeEx = intValue; else SHOW_XML_WARNING("Missing look type/typeex"); if(readXMLInteger(p, "corpse", intValue)) mType->lookCorpse = intValue; if(readXMLInteger(p, "corpseUniqueId", intValue) || readXMLInteger(p, "corpseUid", intValue)) mType->corpseUnique = intValue; if(readXMLInteger(p, "corpseActionId", intValue) || readXMLInteger(p, "corpseAid", intValue)) mType->corpseAction = intValue; } else if(!xmlStrcmp(p->name, (const xmlChar*)"attacks")) { xmlNodePtr tmpNode = p->children; while(tmpNode) { if(!xmlStrcmp(tmpNode->name, (const xmlChar*)"attack")) { spellBlock_t sb; if(deserializeSpell(tmpNode, sb, monsterName)) mType->spellAttackList.push_back(sb); else SHOW_XML_WARNING("Cant load spell"); } tmpNode = tmpNode->next; } } else if(!xmlStrcmp(p->name, (const xmlChar*)"defenses")) { if(readXMLInteger(p, "defense", intValue)) mType->defense = intValue; if(readXMLInteger(p, "armor", intValue)) mType->armor = intValue; xmlNodePtr tmpNode = p->children; while(tmpNode) { if(!xmlStrcmp(tmpNode->name, (const xmlChar*)"defense")) { spellBlock_t sb; if(deserializeSpell(tmpNode, sb, monsterName)) mType->spellDefenseList.push_back(sb); else SHOW_XML_WARNING("Cant load spell"); } tmpNode = tmpNode->next; } } else if(!xmlStrcmp(p->name, (const xmlChar*)"immunities")) { xmlNodePtr tmpNode = p->children; while(tmpNode) { if(!xmlStrcmp(tmpNode->name, (const xmlChar*)"immunity")) { if(readXMLString(tmpNode, "name", strValue)) { std::string tmpStrValue = asLowerCaseString(strValue); if(tmpStrValue == "physical") { mType->damageImmunities |= COMBAT_PHYSICALDAMAGE; mType->conditionImmunities |= CONDITION_PHYSICAL; } else if(tmpStrValue == "energy") { mType->damageImmunities |= COMBAT_ENERGYDAMAGE; mType->conditionImmunities |= CONDITION_ENERGY; } else if(tmpStrValue == "fire") { mType->damageImmunities |= COMBAT_FIREDAMAGE; mType->conditionImmunities |= CONDITION_FIRE; } else if(tmpStrValue == "poison" || tmpStrValue == "earth") { mType->damageImmunities |= COMBAT_EARTHDAMAGE; mType->conditionImmunities |= CONDITION_POISON; } else if(tmpStrValue == "ice") { mType->damageImmunities |= COMBAT_ICEDAMAGE; mType->conditionImmunities |= CONDITION_FREEZING; } else if(tmpStrValue == "holy") { mType->damageImmunities |= COMBAT_HOLYDAMAGE; mType->conditionImmunities |= CONDITION_DAZZLED; } else if(tmpStrValue == "death") { mType->damageImmunities |= COMBAT_DEATHDAMAGE; mType->conditionImmunities |= CONDITION_CURSED; } else if(tmpStrValue == "drown") { mType->damageImmunities |= COMBAT_DROWNDAMAGE; mType->conditionImmunities |= CONDITION_DROWN; } else if(tmpStrValue == "lifedrain") mType->damageImmunities |= COMBAT_LIFEDRAIN; else if(tmpStrValue == "manadrain") mType->damageImmunities |= COMBAT_MANADRAIN; else if(tmpStrValue == "paralyze") mType->conditionImmunities |= CONDITION_PARALYZE; else if(tmpStrValue == "outfit") mType->conditionImmunities |= CONDITION_OUTFIT; else if(tmpStrValue == "drunk") mType->conditionImmunities |= CONDITION_DRUNK; else if(tmpStrValue == "invisible") mType->conditionImmunities |= CONDITION_INVISIBLE; else SHOW_XML_WARNING("Unknown immunity name " << strValue); } else if(readXMLString(tmpNode, "physical", strValue) && booleanString(strValue)) { mType->damageImmunities |= COMBAT_PHYSICALDAMAGE; //mType->conditionImmunities |= CONDITION_PHYSICAL; } else if(readXMLString(tmpNode, "energy", strValue) && booleanString(strValue)) { mType->damageImmunities |= COMBAT_ENERGYDAMAGE; mType->conditionImmunities |= CONDITION_ENERGY; } else if(readXMLString(tmpNode, "fire", strValue) && booleanString(strValue)) { mType->damageImmunities |= COMBAT_FIREDAMAGE; mType->conditionImmunities |= CONDITION_FIRE; } else if((readXMLString(tmpNode, "poison", strValue) || readXMLString(tmpNode, "earth", strValue)) && booleanString(strValue)) { mType->damageImmunities |= COMBAT_EARTHDAMAGE; mType->conditionImmunities |= CONDITION_POISON; } else if(readXMLString(tmpNode, "drown", strValue) && booleanString(strValue)) { mType->damageImmunities |= COMBAT_DROWNDAMAGE; mType->conditionImmunities |= CONDITION_DROWN; } else if(readXMLString(tmpNode, "ice", strValue) && booleanString(strValue)) { mType->damageImmunities |= COMBAT_ICEDAMAGE; mType->conditionImmunities |= CONDITION_FREEZING; } else if(readXMLString(tmpNode, "holy", strValue) && booleanString(strValue)) { mType->damageImmunities |= COMBAT_HOLYDAMAGE; mType->conditionImmunities |= CONDITION_DAZZLED; } else if(readXMLString(tmpNode, "death", strValue) && booleanString(strValue)) { mType->damageImmunities |= COMBAT_DEATHDAMAGE; mType->conditionImmunities |= CONDITION_CURSED; } else if(readXMLString(tmpNode, "lifedrain", strValue) && booleanString(strValue)) mType->damageImmunities |= COMBAT_LIFEDRAIN; else if(readXMLString(tmpNode, "manadrain", strValue) && booleanString(strValue)) mType->damageImmunities |= COMBAT_LIFEDRAIN; else if(readXMLString(tmpNode, "paralyze", strValue) && booleanString(strValue)) mType->conditionImmunities |= CONDITION_PARALYZE; else if(readXMLString(tmpNode, "outfit", strValue) && booleanString(strValue)) mType->conditionImmunities |= CONDITION_OUTFIT; else if(readXMLString(tmpNode, "drunk", strValue) && booleanString(strValue)) mType->conditionImmunities |= CONDITION_DRUNK; else if(readXMLString(tmpNode, "invisible", strValue) && booleanString(strValue)) mType->conditionImmunities |= CONDITION_INVISIBLE; } tmpNode = tmpNode->next; } } else if(!xmlStrcmp(p->name, (const xmlChar*)"voices")) { if(readXMLInteger(p, "speed", intValue) || readXMLInteger(p, "interval", intValue)) mType->yellSpeedTicks = intValue; else SHOW_XML_WARNING("Missing voices.speed"); if(readXMLInteger(p, "chance", intValue)) mType->yellChance = intValue; else SHOW_XML_WARNING("Missing voices.chance"); xmlNodePtr tmpNode = p->children; while(tmpNode) { if(!xmlStrcmp(tmpNode->name, (const xmlChar*)"voice")) { voiceBlock_t vb; vb.text = ""; vb.yellText = false; if(readXMLString(tmpNode, "sentence", strValue)) vb.text = strValue; else SHOW_XML_WARNING("Missing voice.sentence"); if(readXMLString(tmpNode, "yell", strValue)) vb.yellText = booleanString(strValue); mType->voiceVector.push_back(vb); } tmpNode = tmpNode->next; } } else if(!xmlStrcmp(p->name, (const xmlChar*)"loot")) { xmlNodePtr tmpNode = p->children; while(tmpNode) { if(tmpNode->type != XML_ELEMENT_NODE) { tmpNode = tmpNode->next; continue; } LootBlock rootBlock; if(loadLoot(tmpNode, rootBlock)) mType->lootItems.push_back(rootBlock); else SHOW_XML_WARNING("Cant load loot"); tmpNode = tmpNode->next; } } else if(!xmlStrcmp(p->name, (const xmlChar*)"elements")) { xmlNodePtr tmpNode = p->children; while(tmpNode) { if(!xmlStrcmp(tmpNode->name, (const xmlChar*)"element")) { if(readXMLInteger(tmpNode, "firePercent", intValue)) mType->elementMap[COMBAT_FIREDAMAGE] = intValue; else if(readXMLInteger(tmpNode, "energyPercent", intValue)) mType->elementMap[COMBAT_ENERGYDAMAGE] = intValue; else if(readXMLInteger(tmpNode, "icePercent", intValue)) mType->elementMap[COMBAT_ICEDAMAGE] = intValue; else if(readXMLInteger(tmpNode, "poisonPercent", intValue) || readXMLInteger(tmpNode, "earthPercent", intValue)) mType->elementMap[COMBAT_EARTHDAMAGE] = intValue; else if(readXMLInteger(tmpNode, "holyPercent", intValue)) mType->elementMap[COMBAT_HOLYDAMAGE] = intValue; else if(readXMLInteger(tmpNode, "deathPercent", intValue)) mType->elementMap[COMBAT_DEATHDAMAGE] = intValue; else if(readXMLInteger(tmpNode, "drownPercent", intValue)) mType->elementMap[COMBAT_DROWNDAMAGE] = intValue; else if(readXMLInteger(tmpNode, "physicalPercent", intValue)) mType->elementMap[COMBAT_PHYSICALDAMAGE] = intValue; else if(readXMLInteger(tmpNode, "lifeDrainPercent", intValue)) mType->elementMap[COMBAT_LIFEDRAIN] = intValue; else if(readXMLInteger(tmpNode, "manaDrainPercent", intValue)) mType->elementMap[COMBAT_MANADRAIN] = intValue; else if(readXMLInteger(tmpNode, "healingPercent", intValue)) mType->elementMap[COMBAT_HEALING] = intValue; else if(readXMLInteger(tmpNode, "undefinedPercent", intValue)) mType->elementMap[COMBAT_UNDEFINEDDAMAGE] = intValue; } tmpNode = tmpNode->next; } } else if(!xmlStrcmp(p->name, (const xmlChar*)"summons")) { if(readXMLInteger(p, "maxSummons", intValue) || readXMLInteger(p, "max", intValue)) mType->maxSummons = intValue; xmlNodePtr tmpNode = p->children; while(tmpNode) { if(!xmlStrcmp(tmpNode->name, (const xmlChar*)"summon")) { uint32_t chance = 100, interval = 1000, amount = 1; if(readXMLInteger(tmpNode, "speed", intValue) || readXMLInteger(tmpNode, "interval", intValue)) interval = intValue; if(readXMLInteger(tmpNode, "chance", intValue)) chance = intValue; if(readXMLInteger(tmpNode, "amount", intValue) || readXMLInteger(tmpNode, "max", intValue)) amount = intValue; if(readXMLString(tmpNode, "name", strValue)) { summonBlock_t sb; sb.name = strValue; sb.interval = interval; sb.chance = chance; sb.amount = amount; mType->summonList.push_back(sb); } else SHOW_XML_WARNING("Missing summon.name"); } tmpNode = tmpNode->next; } } else if(!xmlStrcmp(p->name, (const xmlChar*)"script")) { xmlNodePtr tmpNode = p->children; while(tmpNode) { if(!xmlStrcmp(tmpNode->name, (const xmlChar*)"event")) { if(readXMLString(tmpNode, "name", strValue)) mType->scriptList.push_back(strValue); else SHOW_XML_WARNING("Missing name for script event"); } tmpNode = tmpNode->next; } } else SHOW_XML_WARNING("Unknown attribute type - " << p->name); p = p->next; } xmlFreeDoc(doc); if(monsterLoad) { static uint32_t id = 0; if(new_mType) { id++; monsterNames[asLowerCaseString(monsterName)] = id; monsters[id] = mType; } return true; } if(new_mType) delete mType; return false; } bool Monsters::loadLoot(xmlNodePtr node, LootBlock& lootBlock) { std::string strValue; if(readXMLString(node, "id", strValue) || readXMLString(node, "ids", strValue)) { IntegerVec idsVec; parseIntegerVec(strValue, idsVec); for(IntegerVec::iterator it = idsVec.begin(); it != idsVec.end(); ++it) { lootBlock.ids.push_back(*it); if(Item::items[(*it)].isContainer()) loadChildLoot(node, lootBlock); } } else if(readXMLString(node, "name", strValue) || readXMLString(node, "names", strValue)) { StringVec names = explodeString(strValue, ";"); for(StringVec::iterator it = names.begin(); it != names.end(); ++it) { uint16_t tmp = Item::items.getItemIdByName(strValue); if(!tmp) continue; lootBlock.ids.push_back(tmp); if(Item::items[tmp].isContainer()) loadChildLoot(node, lootBlock); } } if(lootBlock.ids.empty()) return false; int32_t intValue; if(readXMLInteger(node, "count", intValue) || readXMLInteger(node, "countmax", intValue)) lootBlock.count = std::max(1, std::min(100, intValue)); else lootBlock.count = 1; if(readXMLInteger(node, "chance", intValue) || readXMLInteger(node, "chance1", intValue)) lootBlock.chance = std::min(MAX_LOOTCHANCE, intValue); else lootBlock.chance = MAX_LOOTCHANCE; if(readXMLInteger(node, "subtype", intValue) || readXMLInteger(node, "subType", intValue)) lootBlock.subType = intValue; if(readXMLInteger(node, "actionId", intValue) || readXMLInteger(node, "actionid", intValue) || readXMLInteger(node, "aid", intValue)) lootBlock.actionId = intValue; if(readXMLInteger(node, "uniqueId", intValue) || readXMLInteger(node, "uniqueid", intValue) || readXMLInteger(node, "uid", intValue)) lootBlock.uniqueId = intValue; if(readXMLString(node, "text", strValue)) lootBlock.text = strValue; return true; } bool Monsters::loadChildLoot(xmlNodePtr node, LootBlock& parentBlock) { if(!node) return false; xmlNodePtr p = node->children, insideNode; while(p) { if(!xmlStrcmp(p->name, (const xmlChar*)"inside")) { insideNode = p->children; while(insideNode) { LootBlock childBlock; if(loadLoot(insideNode, childBlock)) parentBlock.childLoot.push_back(childBlock); insideNode = insideNode->next; } p = p->next; continue; } LootBlock childBlock; if(loadLoot(p, childBlock)) parentBlock.childLoot.push_back(childBlock); p = p->next; } return true; } MonsterType* Monsters::getMonsterType(const std::string& name) { uint32_t mId = getIdByName(name); if(mId != 0) return getMonsterType(mId); return NULL; } MonsterType* Monsters::getMonsterType(uint32_t mid) { MonsterMap::iterator it = monsters.find(mid); if(it != monsters.end()) return it->second; return NULL; } uint32_t Monsters::getIdByName(const std::string& name) { std::string tmp = name; MonsterNameMap::iterator it = monsterNames.find(asLowerCaseString(tmp)); if(it != monsterNames.end()) return it->second; return 0; } Monsters::~Monsters() { loaded = false; for(MonsterMap::iterator it = monsters.begin(); it != monsters.end(); it++) delete it->second; } Editado Março 21, 2021 4 anos por elielder coloquei monster cpp (veja o histórico de edições)
Participe da conversa
Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.