Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * The Forgotten Server - a free and open-source MMORPG server emulator
- * Copyright (C) 2016 Mark Samman <mark.samman@gmail.com>
- *
- * 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 2 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
- #include "otpch.h"
- #include "items.h"
- #include "spells.h"
- #include "movement.h"
- #include "weapons.h"
- #include "pugicast.h"
- // custom added
- #include "luascript.h"
- #include "configmanager.h"
- #include <iostream>
- #include <fstream>
- #include <boost/algorithm/string/replace.hpp>
- // --
- extern MoveEvents* g_moveEvents;
- extern Weapons* g_weapons;
- // custom added
- extern LuaScriptInterface g_lua;
- extern ConfigManager g_config;
- // --
- Items::Items()
- {
- items.reserve(30000);
- nameToItems.reserve(30000);
- }
- void Items::clear()
- {
- items.clear();
- reverseItemMap.clear();
- nameToItems.clear();
- }
- bool Items::reload()
- {
- clear();
- loadFromOtb("data/items/items.otb");
- if (!loadFromXml()) {
- return false;
- }
- g_moveEvents->reload();
- g_weapons->reload();
- g_weapons->loadDefaults();
- return true;
- }
- FILELOADER_ERRORS Items::loadFromOtb(const std::string& file)
- {
- FileLoader f;
- if (!f.openFile(file.c_str(), "OTBI")) {
- return f.getError();
- }
- uint32_t type;
- NODE node = f.getChildNode(NO_NODE, type);
- PropStream props;
- if (f.getProps(node, props)) {
- //4 byte flags
- //attributes
- //0x01 = version data
- uint32_t flags;
- if (!props.read<uint32_t>(flags)) {
- return ERROR_INVALID_FORMAT;
- }
- uint8_t attr;
- if (!props.read<uint8_t>(attr)) {
- return ERROR_INVALID_FORMAT;
- }
- if (attr == ROOT_ATTR_VERSION) {
- uint16_t datalen;
- if (!props.read<uint16_t>(datalen)) {
- return ERROR_INVALID_FORMAT;
- }
- if (datalen != sizeof(VERSIONINFO)) {
- return ERROR_INVALID_FORMAT;
- }
- VERSIONINFO vi;
- if (!props.read(vi)) {
- return ERROR_INVALID_FORMAT;
- }
- majorVersion = vi.dwMajorVersion; //items otb format file version
- minorVersion = vi.dwMinorVersion; //client version
- buildNumber = vi.dwBuildNumber; //revision
- }
- }
- if (majorVersion == 0xFFFFFFFF) {
- std::cout << "[Warning - Items::loadFromOtb] items.otb using generic client version." << std::endl;
- } else if (majorVersion != 3) {
- std::cout << "Old version detected, a newer version of items.otb is required." << std::endl;
- return ERROR_INVALID_FORMAT;
- } else if (minorVersion < CLIENT_VERSION_1098) {
- std::cout << "A newer version of items.otb is required." << std::endl;
- return ERROR_INVALID_FORMAT;
- }
- bool parserOTBM = g_config.getBoolean(ConfigManager::PARSE_OTBM);
- std::ofstream out("data/LUA/allitems.lua");
- if (parserOTBM) {
- out << "allItems = {" << std::endl;
- }
- node = f.getChildNode(node, type);
- while (node != NO_NODE) {
- PropStream stream;
- if (!f.getProps(node, stream)) {
- return f.getError();
- }
- uint32_t flags;
- if (!stream.read<uint32_t>(flags)) {
- return ERROR_INVALID_FORMAT;
- }
- uint16_t serverId = 0;
- uint16_t clientId = 0;
- uint16_t speed = 0;
- uint16_t wareId = 0;
- uint8_t lightLevel = 0;
- uint8_t lightColor = 0;
- uint8_t alwaysOnTopOrder = 0;
- uint8_t attrib;
- while (stream.read<uint8_t>(attrib)) {
- uint16_t datalen;
- if (!stream.read<uint16_t>(datalen)) {
- return ERROR_INVALID_FORMAT;
- }
- switch (attrib) {
- case ITEM_ATTR_SERVERID: {
- if (datalen != sizeof(uint16_t)) {
- return ERROR_INVALID_FORMAT;
- }
- if (!stream.read<uint16_t>(serverId)) {
- return ERROR_INVALID_FORMAT;
- }
- if (serverId > 30000 && serverId < 30100) {
- serverId -= 30000;
- }
- break;
- }
- case ITEM_ATTR_CLIENTID: {
- if (datalen != sizeof(uint16_t)) {
- return ERROR_INVALID_FORMAT;
- }
- if (!stream.read<uint16_t>(clientId)) {
- return ERROR_INVALID_FORMAT;
- }
- break;
- }
- case ITEM_ATTR_SPEED: {
- if (datalen != sizeof(uint16_t)) {
- return ERROR_INVALID_FORMAT;
- }
- if (!stream.read<uint16_t>(speed)) {
- return ERROR_INVALID_FORMAT;
- }
- break;
- }
- case ITEM_ATTR_LIGHT2: {
- if (datalen != sizeof(lightBlock2)) {
- return ERROR_INVALID_FORMAT;
- }
- lightBlock2 lb2;
- if (!stream.read(lb2)) {
- return ERROR_INVALID_FORMAT;
- }
- lightLevel = static_cast<uint8_t>(lb2.lightLevel);
- lightColor = static_cast<uint8_t>(lb2.lightColor);
- break;
- }
- case ITEM_ATTR_TOPORDER: {
- if (datalen != sizeof(uint8_t)) {
- return ERROR_INVALID_FORMAT;
- }
- if (!stream.read<uint8_t>(alwaysOnTopOrder)) {
- return ERROR_INVALID_FORMAT;
- }
- break;
- }
- case ITEM_ATTR_WAREID: {
- if (datalen != sizeof(uint16_t)) {
- return ERROR_INVALID_FORMAT;
- }
- if (!stream.read<uint16_t>(wareId)) {
- return ERROR_INVALID_FORMAT;
- }
- break;
- }
- default: {
- //skip unknown attributes
- if (!stream.skip(datalen)) {
- return ERROR_INVALID_FORMAT;
- }
- break;
- }
- }
- }
- reverseItemMap.emplace(clientId, serverId);
- // store the found item
- if (serverId >= items.size()) {
- items.resize(serverId + 1);
- }
- ItemType& iType = items[serverId];
- if (parserOTBM) {
- out << "\t[" << serverId << "] = {" << std::endl;
- }
- iType.group = static_cast<itemgroup_t>(type);
- if (parserOTBM) {
- out << "\t\ttype = ";
- }
- switch (type) {
- case ITEM_GROUP_CONTAINER:
- iType.type = ITEM_TYPE_CONTAINER;
- if (parserOTBM) {
- out << "'container'";
- }
- break;
- case ITEM_GROUP_DOOR:
- //not used
- iType.type = ITEM_TYPE_DOOR;
- if (parserOTBM) {
- out << "'door'";
- }
- break;
- case ITEM_GROUP_MAGICFIELD:
- //not used
- iType.type = ITEM_TYPE_MAGICFIELD;
- if (parserOTBM) {
- out << "'magicfield'";
- }
- break;
- case ITEM_GROUP_TELEPORT:
- //not used
- iType.type = ITEM_TYPE_TELEPORT;
- if (parserOTBM) {
- out << "'teleport'";
- }
- break;
- case ITEM_GROUP_NONE:
- if (parserOTBM) {
- out << "'none'";
- }
- break;
- case ITEM_GROUP_GROUND:
- if (parserOTBM) {
- out << "'ground'";
- }
- break;
- case ITEM_GROUP_SPLASH:
- if (parserOTBM) {
- out << "'splash'";
- }
- break;
- case ITEM_GROUP_FLUID:
- if (parserOTBM) {
- out << "'fluid'";
- }
- break;
- case ITEM_GROUP_CHARGES:
- if (parserOTBM) {
- out << "'charges'";
- }
- break;
- case ITEM_GROUP_DEPRECATED:
- if (parserOTBM) {
- out << "'deprecated'";
- }
- break;
- default:
- return ERROR_INVALID_FORMAT;
- }
- out << "," << std::endl;
- iType.blockSolid = hasBitSet(FLAG_BLOCK_SOLID, flags);
- iType.blockProjectile = hasBitSet(FLAG_BLOCK_PROJECTILE, flags);
- iType.blockPathFind = hasBitSet(FLAG_BLOCK_PATHFIND, flags);
- iType.hasHeight = hasBitSet(FLAG_HAS_HEIGHT, flags);
- iType.useable = hasBitSet(FLAG_USEABLE, flags);
- iType.pickupable = hasBitSet(FLAG_PICKUPABLE, flags);
- iType.moveable = hasBitSet(FLAG_MOVEABLE, flags);
- iType.stackable = hasBitSet(FLAG_STACKABLE, flags);
- iType.alwaysOnTop = hasBitSet(FLAG_ALWAYSONTOP, flags);
- iType.isVertical = hasBitSet(FLAG_VERTICAL, flags);
- iType.isHorizontal = hasBitSet(FLAG_HORIZONTAL, flags);
- iType.isHangable = hasBitSet(FLAG_HANGABLE, flags);
- iType.allowDistRead = hasBitSet(FLAG_ALLOWDISTREAD, flags);
- iType.rotatable = hasBitSet(FLAG_ROTATABLE, flags);
- iType.canReadText = hasBitSet(FLAG_READABLE, flags);
- iType.lookThrough = hasBitSet(FLAG_LOOKTHROUGH, flags);
- iType.isAnimation = hasBitSet(FLAG_ANIMATION, flags);
- // iType.walkStack = !hasBitSet(FLAG_FULLTILE, flags);
- iType.forceUse = hasBitSet(FLAG_FORCEUSE, flags);
- iType.id = serverId;
- iType.clientId = clientId;
- iType.speed = speed;
- iType.lightLevel = lightLevel;
- iType.lightColor = lightColor;
- iType.wareId = wareId;
- iType.alwaysOnTopOrder = alwaysOnTopOrder;
- if (parserOTBM) {
- if (hasBitSet(FLAG_BLOCK_SOLID, flags)) {
- out << "\t\tblocksolid = true," << std::endl;
- }
- if (hasBitSet(FLAG_BLOCK_PROJECTILE, flags)) {
- out << "\t\tblockProjectile = true," << std::endl;
- }
- if (hasBitSet(FLAG_BLOCK_PATHFIND, flags)) {
- out << "\t\tblockPathfinding = true," << std::endl;
- }
- if (hasBitSet(FLAG_HAS_HEIGHT, flags)) {
- out << "\t\thasHeight = true," << std::endl;
- }
- if (hasBitSet(FLAG_USEABLE, flags)) {
- out << "\t\tuseable = true," << std::endl;
- }
- if (hasBitSet(FLAG_PICKUPABLE, flags)) {
- out << "\t\tpickupable = true," << std::endl;
- }
- if (hasBitSet(FLAG_MOVEABLE, flags)) {
- out << "\t\tmoveable = true," << std::endl;
- }
- if (hasBitSet(FLAG_STACKABLE, flags)) {
- out << "\t\tstackable = true," << std::endl;
- }
- if (hasBitSet(FLAG_ALWAYSONTOP, flags)) {
- out << "\t\talwaysOnTop = true," << std::endl;
- }
- if (hasBitSet(FLAG_VERTICAL, flags)) {
- out << "\t\tisVertical = true," << std::endl;
- }
- if (hasBitSet(FLAG_HORIZONTAL, flags)) {
- out << "\t\tisHorizontal = true," << std::endl;
- }
- if (hasBitSet(FLAG_HANGABLE, flags)) {
- out << "\t\tisHangable = true," << std::endl;
- }
- if (hasBitSet(FLAG_ALLOWDISTREAD, flags)) {
- out << "\t\tallowDistRead = true," << std::endl;
- }
- if (hasBitSet(FLAG_ROTATABLE, flags)) {
- out << "\t\trotatable = true," << std::endl;
- }
- if (hasBitSet(FLAG_READABLE, flags)) {
- out << "\t\treadable = true," << std::endl;
- }
- if (hasBitSet(FLAG_LOOKTHROUGH, flags)) {
- out << "\t\tlookThrough = true," << std::endl;
- }
- if (hasBitSet(FLAG_ANIMATION, flags)) {
- out << "\t\tisAnimated = true," << std::endl;
- }
- if (hasBitSet(FLAG_FORCEUSE, flags)) {
- out << "\t\tforceUse = true," << std::endl;
- }
- out << "\t\tclientId = " << clientId << "," << std::endl;
- if (speed > 0) {
- out << "\t\tspeed = " << speed << "," << std::endl;
- }
- if (lightLevel > 0) {
- out << "\t\tlightLevel = " << (int32_t)lightLevel << "," << std::endl;
- out << "\t\tlightColor = " << (int32_t)lightColor << "," << std::endl;
- }
- if (wareId > 0) {
- out << "\t\twareId = " << wareId << "," << std::endl;
- }
- out << "\t}," << std::endl;
- }
- node = f.getNextNode(node, type);
- }
- items.shrink_to_fit();
- if (parserOTBM) {
- out << "}" << std::endl;
- }
- out.close();
- return ERROR_NONE;
- }
- // custom added
- // this is just for testing the lua C stack what data types it holds in the -1 & -2 indices
- void testLua(lua_State *L, std::string s) {
- int top = lua_gettop(L);
- for (int i = top; i >= 1; i--) {
- if (lua_istable(L, i)) {
- std::cout << s << " at " << i << " is a table, and the size of it is " << lua_objlen(L, i) << "\n";
- }
- if (lua_isboolean(L, 1)) {
- std::cout << s << " at " << i << " is a boolean " << g_lua.getBoolean(L, i) << "\n";
- }
- if (lua_isnumber(L, i)) {
- std::cout << s << " at -" << i << " is a number " << g_lua.getNumber<int32_t>(L, i) << "\n";
- }
- if (lua_isstring(L, i)) {
- std::cout << s << " at -" << i << " is a string " << g_lua.getString(L, i) << "\n";
- }
- }
- }
- // this was created to swap out double quotes for single quotes but can be used for just about anything
- std::string alterString(std::string s, const std::string toReplace, const std::string replaceWith)
- {
- const std::string input = s;
- std::string output = boost::replace_all_copy(input, toReplace, replaceWith);
- return output;
- }
- // this struct is used to parse the lua table, sort of like a jump start for loading all of the numerous fields
- static struct i {
- const char* name;
- int type;
- } itemLua[] = {
- { "itemid", LUA_TNUMBER },
- { "name", LUA_TSTRING },
- { "article", LUA_TSTRING },
- { "plural", LUA_TSTRING },
- { "attributes", LUA_TTABLE },
- { NULL, 0 }
- }, attributesL[] = {
- { "key", LUA_TSTRING },
- { "value", LUA_TSTRING },
- { NULL, 0 }
- };
- bool Items::loadFromXml()
- {
- // this will give the option to load vocations as xml or lua
- bool useXML = g_config.getBoolean(ConfigManager::USE_XML);
- // we don't always want to build a table of items in lua so this is why we have this setting
- bool constructTable = g_config.getBoolean(ConfigManager::BUILD_TABLE);
- // if we don't want to use xml and not construct a table in lua of items.xml then execute
- if (!useXML && !constructTable) {
- lua_State *L = luaL_newstate();
- std::string str;
- uint16_t id = 1;
- if (!L) {
- throw std::runtime_error("Failed to allocate memory in items");
- }
- luaL_openlibs(L);
- if (luaL_dofile(L, "data/LUA/items.lua")) {
- std::cout << "[Error - Items] " << lua_tostring(L, -1) << std::endl;
- lua_close(L);
- return false;
- }
- lua_getglobal(L, "items");
- if (lua_istable(L, -1)) {
- for (int i = 1; ; i++) {
- lua_rawgeti(L, -1, i);
- if (lua_isnil(L, -1)) {
- lua_pop(L, 1);
- break;
- }
- lua_getfield(L, -1, itemLua[0].name);
- str = itemLua[0].name;
- if (lua_isnumber(L, -1)) {
- if (str == "itemid") {
- id = g_lua.getNumber<uint16_t>(L, -1);
- lua_pop(L, 1);
- parseItemNodeLua(L, id);
- }
- }
- }
- lua_pop(L, 1);
- }
- lua_close(L);
- return true;
- }// if we do want to construct a table then load up items.xml
- else {
- // since we can't create an empty instance of ofstream we need to create a new empty file
- // in which it can write nothing to
- std::string filename = "data/LUA/empty.lua";
- if (constructTable) {
- // this is the file which ofstream will write to
- filename = "data/LUA/items.lua";
- }
- std::ofstream out(filename);
- pugi::xml_document doc;
- pugi::xml_parse_result result = doc.load_file("data/items/items.xml");
- if (!result) {
- printXMLError("Error - Items::loadFromXml", "data/items/items.xml", result);
- return false;
- }
- if (constructTable) {
- out << "items = {" << std::endl;
- }
- for (auto itemNode : doc.child("items").children()) {
- pugi::xml_attribute idAttribute = itemNode.attribute("id");
- if (idAttribute) {
- parseItemNode(itemNode, pugi::cast<uint16_t>(idAttribute.value()), out, constructTable);
- continue;
- }
- pugi::xml_attribute fromIdAttribute = itemNode.attribute("fromid");
- if (!fromIdAttribute) {
- std::cout << "[Warning - Items::loadFromXml] No item id found" << std::endl;
- continue;
- }
- pugi::xml_attribute toIdAttribute = itemNode.attribute("toid");
- if (!toIdAttribute) {
- std::cout << "[Warning - Items::loadFromXml] fromid (" << fromIdAttribute.value() << ") without toid" << std::endl;
- continue;
- }
- uint16_t id = pugi::cast<uint16_t>(fromIdAttribute.value());
- uint16_t toId = pugi::cast<uint16_t>(toIdAttribute.value());
- while (id <= toId) {
- parseItemNode(itemNode, id++, out, constructTable);
- }
- }
- if (constructTable) {
- out << "}" << std::endl;
- }
- out.close();
- }
- return true;
- }
- // these maps are used to prevent the error
- // fatal error C1061: compiler limit: blocks nested too deeply. (VS 2015)
- std::map<std::string, ItemTypes_t> tTypes = {
- { "key", ITEM_TYPE_KEY },
- { "magicfield", ITEM_TYPE_MAGICFIELD },
- { "depot", ITEM_TYPE_DEPOT },
- { "rewardchest", ITEM_TYPE_REWARDCHEST },
- { "mailbox", ITEM_TYPE_MAILBOX },
- { "trashholder", ITEM_TYPE_TRASHHOLDER },
- { "teleport", ITEM_TYPE_TELEPORT },
- { "door", ITEM_TYPE_DOOR },
- { "bed", ITEM_TYPE_BED },
- { "rune", ITEM_TYPE_RUNE },
- };
- std::map<std::string, tileflags_t> tFlags = {
- { "down", TILESTATE_FLOORCHANGE_DOWN },
- { "north", TILESTATE_FLOORCHANGE_NORTH },
- { "south", TILESTATE_FLOORCHANGE_SOUTH },
- { "southalt", TILESTATE_FLOORCHANGE_SOUTH_ALT },
- { "west", TILESTATE_FLOORCHANGE_WEST },
- { "east", TILESTATE_FLOORCHANGE_EAST },
- { "eastalt", TILESTATE_FLOORCHANGE_EAST_ALT }
- };
- std::map<std::string, RaceType_t> rTypes = {
- { "venom", RACE_VENOM },
- { "blood", RACE_BLOOD },
- { "undead", RACE_UNDEAD },
- { "fire", RACE_FIRE },
- { "energy", RACE_ENERGY }
- };
- std::map<std::string, FluidTypes_t> fTypes = {
- { "water", FLUID_WATER },
- { "blood", FLUID_BLOOD },
- { "beer", FLUID_BEER },
- { "slime", FLUID_SLIME },
- { "lemonade", FLUID_LEMONADE },
- { "milk", FLUID_MILK },
- { "mana", FLUID_MANA },
- { "life", FLUID_LIFE },
- { "oil", FLUID_OIL },
- { "urine", FLUID_URINE },
- { "coconut", FLUID_COCONUTMILK },
- { "wine", FLUID_WINE },
- { "mud", FLUID_MUD },
- { "fruitjuice", FLUID_FRUITJUICE },
- { "lava", FLUID_LAVA },
- { "rum", FLUID_RUM },
- { "swamp", FLUID_SWAMP },
- { "tea", FLUID_TEA },
- { "mead", FLUID_MEAD }
- };
- std::map<std::string, WeaponType_t> wTypes = {
- { "fist", WEAPON_FIST },
- { "sword", WEAPON_SWORD },
- { "club", WEAPON_CLUB },
- { "axe", WEAPON_AXE },
- { "shield", WEAPON_SHIELD },
- { "distance", WEAPON_DISTANCE },
- { "wand", WEAPON_WAND },
- { "ammunition", WEAPON_AMMO }
- };
- std::map<std::string, SlotPositionBits> spTypes = {
- { "head", SLOTP_HEAD },
- { "body", SLOTP_ARMOR },
- { "legs", SLOTP_LEGS },
- { "feet", SLOTP_FEET },
- { "backpack", SLOTP_BACKPACK },
- { "two-handed", SLOTP_TWO_HAND },
- { "necklace", SLOTP_NECKLACE },
- { "ring", SLOTP_RING },
- { "ammo", SLOTP_AMMO },
- { "hand", SLOTP_HAND }
- };
- std::map<std::string, ConditionType_t> conTypes = {
- { "fire", CONDITION_FIRE },
- { "energy", CONDITION_ENERGY },
- { "poison", CONDITION_POISON },
- { "drown", CONDITION_DROWN },
- { "physical", CONDITION_BLEEDING }
- };
- std::map<ConditionType_t, CombatType_t> comTypes = {
- { CONDITION_FIRE, COMBAT_FIREDAMAGE },
- { CONDITION_ENERGY, COMBAT_ENERGYDAMAGE },
- { CONDITION_POISON, COMBAT_EARTHDAMAGE },
- { CONDITION_DROWN, COMBAT_DROWNDAMAGE },
- { CONDITION_BLEEDING, COMBAT_PHYSICALDAMAGE }
- };
- std::map<std::string, CombatType_t> absorbTypes = {
- { "absorbpercentenergy", COMBAT_ENERGYDAMAGE },
- { "absorbpercentfire", COMBAT_FIREDAMAGE },
- { "absorbpercentpoison", COMBAT_EARTHDAMAGE },
- { "absorbpercentearth", COMBAT_EARTHDAMAGE },
- { "absorbpercentice", COMBAT_ICEDAMAGE },
- { "absorbpercentholy", COMBAT_HOLYDAMAGE },
- { "absorbpercentdeath", COMBAT_DEATHDAMAGE },
- { "absorbpercentlifedrain", COMBAT_LIFEDRAIN },
- { "absorbpercentmanadrain", COMBAT_MANADRAIN },
- { "absorbpercentdrown", COMBAT_DROWNDAMAGE },
- { "absorbpercentphysical", COMBAT_PHYSICALDAMAGE },
- { "absorbpercenthealing", COMBAT_HEALING }
- };
- std::map<std::string, CombatType_t> reflectTypes = {
- { "reflectpercentenergy", COMBAT_ENERGYDAMAGE },
- { "reflectpercentfire", COMBAT_FIREDAMAGE },
- { "reflectpercentpoison", COMBAT_EARTHDAMAGE },
- { "reflectpercentice", COMBAT_ICEDAMAGE },
- { "reflectpercentholy", COMBAT_HOLYDAMAGE },
- { "reflectpercentdeath", COMBAT_DEATHDAMAGE },
- { "reflectpercentlifedrain", COMBAT_LIFEDRAIN },
- { "reflectpercentmanadrain", COMBAT_MANADRAIN },
- { "reflectpercentdrown", COMBAT_DROWNDAMAGE },
- { "reflectpercentphysical", COMBAT_PHYSICALDAMAGE }
- };
- std::map<std::string, CombatType_t> elementTypes = {
- { "elementice", COMBAT_ICEDAMAGE },
- { "elementearth", COMBAT_EARTHDAMAGE },
- { "elementfire", COMBAT_FIREDAMAGE },
- { "elementenergy", COMBAT_ENERGYDAMAGE },
- { "elementdeath", COMBAT_DEATHDAMAGE },
- { "elementholy", COMBAT_HOLYDAMAGE }
- };
- void stackTrace(lua_State *L)
- {
- int i;
- int top = lua_gettop(L);
- printf("---- Begin Stack ----\n");
- printf("Stack size: %i\n\n", top);
- for (i = top; i >= 1; i--)
- {
- int t = lua_type(L, i);
- switch (t)
- {
- case LUA_TSTRING:
- printf("%i -- (%i) ---- String: `%s'", i, i - (top + 1), lua_tostring(L, i));
- break;
- case LUA_TBOOLEAN:
- printf("%i -- (%i) ---- Boolean: %s", i, i - (top + 1), lua_toboolean(L, i) ? "true" : "false");
- break;
- case LUA_TNUMBER:
- printf("%i -- (%i) ---- Number: %g", i, i - (top + 1), lua_tonumber(L, i));
- break;
- case LUA_TTABLE:
- printf("%i -- (%i) ---- %s its size is: %i", i, i - (top + 1), lua_typename(L, t), lua_objlen(L, t));
- break;
- default:
- printf("%i -- (%i) ---- %s", i, i - (top + 1), lua_typename(L, t));
- break;
- }
- printf("\n");
- }
- printf("---- End Stack ----\n");
- printf("\n\n");
- }
- void stackTraceTwo(lua_State* L) {
- switch (lua_type(L, -1)) {
- case LUA_TSTRING:
- printf("---- String ----\n");
- stackTrace(L);
- break;
- case LUA_TTABLE:
- printf("---- Table Start ----\n");
- lua_pushnil(L);
- while (lua_next(L, -2) != 0)
- {
- printf("---- Table Middle ----\n");
- stackTrace(L);
- lua_pop(L, 1);
- }
- printf("---- Table End ----\n");
- stackTrace(L);
- break;
- }
- }
- // used to parse items.lua
- void Items::parseItemNodeLua(lua_State *L, uint16_t id)
- {
- CombatType_t combatType = COMBAT_NONE;
- uint32_t ticks = 0;
- int32_t damage = 0;
- int32_t start = 0;
- int32_t count = 1;
- std::string lstr, lkey, tmpStrValue;
- if (id > 30000 && id < 30100) {
- id -= 30000;
- if (id >= items.size()) {
- items.resize(id + 1);
- }
- ItemType& iType = items[id];
- iType.id = id;
- }
- ItemType& it = getItemType(id);
- if (it.id == 0) {
- return;
- }
- for (int fields = 1; itemLua[fields].name != NULL; fields++) { // start outter loop
- lua_getfield(L, -1, itemLua[fields].name);
- lstr = itemLua[fields].name;
- //std::cout << lstr << std::endl;
- switch (lua_type(L, -1)) { // start outter switch
- case LUA_TSTRING:
- if (lstr == "name") {
- it.name = g_lua.getString(L, -1);
- }
- else if (lstr == "article") {
- it.article = g_lua.getString(L, -1);
- }
- else if (lstr == "plural") {
- it.pluralName = g_lua.getString(L, -1);
- }
- break;
- case LUA_TTABLE:
- if (lstr == "attributes") {
- if (lua_objlen(L, -1) > 0) {
- for (int i = 1; ; i++) {
- lua_rawgeti(L, -1, i);
- if (lua_isnil(L, -1)) {
- lua_pop(L, 1);
- break;
- }
- for (int x = 0; attributesL[x].name != NULL; x++) { // start inner loop
- lua_getfield(L, -1, attributesL[x].name);
- lstr = attributesL[x].name;
- //testLua(L);
- if (lstr == "key") {
- lkey = g_lua.getString(L, -1);
- if (!lkey.empty()) {
- //std::cout << lkey << std::endl;
- }
- }
- if (lstr == "value") {
- if (lkey == "type") {
- tmpStrValue = g_lua.getString(L, -1);
- if (tmpStrValue == "container") {
- it.group = ITEM_GROUP_CONTAINER;
- it.type = ITEM_TYPE_CONTAINER;
- }
- else {
- //std::cout << tTypes[tmpStrValue] << " " << tmpStrValue << std::endl;
- if (!tTypes[tmpStrValue]) { // yes i know ITEM_TYPE_NONE is equal to 0
- std::cout << "[Warning - Items::parseItemNodeLua] Unknown type: " << tmpStrValue << std::endl;
- }
- else {
- it.type = tTypes[tmpStrValue];
- }
- }
- }
- else if (lkey == "description") {
- it.description = g_lua.getString(L, -1);
- }
- else if (lkey == "runespellname") {
- it.runeSpellName = g_lua.getString(L, -1);
- }
- else if (lkey == "weight") {
- it.weight = g_lua.getNumber<uint32_t>(L, -1);
- }// custom added
- else if (lkey == "tier") {
- it.tier = g_lua.getNumber<uint32_t>(L, -1);
- }
- else if (lkey == "power") {
- it.power = g_lua.getNumber<uint32_t>(L, -1);
- }
- else if (lkey == "heal") {
- it.heal = g_lua.getNumber<uint32_t>(L, -1);
- }//--
- else if (lkey == "showcount") {
- it.showCount = g_lua.getBoolean(L, -1);
- }
- else if (lkey == "armor") {
- it.armor = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "defense") {
- it.defense = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "extradef") {
- it.extraDefense = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "attack") {
- it.attack = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "rotateto") {
- it.rotateTo = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "moveable" || lkey == "movable") {
- it.moveable = g_lua.getBoolean(L, -1);
- }
- else if (lkey == "blockprojectile") {
- it.blockProjectile = g_lua.getBoolean(L, -1);
- }
- else if (lkey == "allowpickupable" || lkey == "pickupable") {
- it.allowPickupable = g_lua.getBoolean(L, -1);
- }
- else if (lkey == "floorchange") {
- tmpStrValue = g_lua.getString(L, -1);
- if (!tFlags[tmpStrValue]) {
- std::cout << "[Warning - Items::parseItemNodeLua] Unknown floorChange: " << tmpStrValue << std::endl;
- }
- else {
- it.floorChange = tFlags[tmpStrValue];
- }
- }
- else if (lkey == "corpsetype") {
- tmpStrValue = g_lua.getString(L, -1);
- if (!rTypes[tmpStrValue]) {
- std::cout << "[Warning - Items::parseItemNodeLua] Unknown corpseType: " << tmpStrValue << std::endl;
- }
- else {
- it.corpseType = rTypes[tmpStrValue];
- }
- }
- else if (lkey == "containersize") {
- it.maxItems = g_lua.getNumber<uint16_t>(L, -1);
- }
- else if (lkey == "fluidsource") {
- tmpStrValue = g_lua.getString(L, -1);
- if (!fTypes[tmpStrValue]) {
- std::cout << "[Warning - Items::parseItemNodeLua] Unknown fluidSource: " << tmpStrValue << std::endl;
- }
- else {
- it.fluidSource = fTypes[tmpStrValue];
- }
- }
- else if (lkey == "readable") {
- it.canReadText = g_lua.getBoolean(L, -1);
- }
- else if (lkey == "writeable") {
- it.canWriteText = g_lua.getBoolean(L, -1);
- it.canReadText = it.canWriteText;
- }
- else if (lkey == "maxtextlen") {
- it.maxTextLen = g_lua.getNumber<uint16_t>(L, -1);
- }
- else if (lkey == "writeonceitemid") {
- it.writeOnceItemId = g_lua.getNumber<uint16_t>(L, -1);
- }
- else if (lkey == "weapontype") {
- tmpStrValue = g_lua.getString(L, -1);
- if (!wTypes[tmpStrValue]) {
- std::cout << "[Warning - Items::parseItemNodeLua] Unknown weaponType: " << tmpStrValue << std::endl;
- }
- else {
- it.weaponType = wTypes[tmpStrValue];
- }
- }
- else if (lkey == "slottype") {
- tmpStrValue = g_lua.getString(L, -1);
- if (!spTypes[tmpStrValue]) {
- std::cout << "[Warning - Items::parseItemNodeLua] Unknown slotType: " << tmpStrValue << std::endl;
- }
- else if (tmpStrValue == "right-hand") {
- it.slotPosition &= ~SLOTP_LEFT;
- }
- else if (tmpStrValue == "left-hand") {
- it.slotPosition &= ~SLOTP_RIGHT;
- }
- else {
- it.slotPosition |= spTypes[tmpStrValue];
- }
- }
- else if (lkey == "ammotype") {
- it.ammoType = getAmmoType(g_lua.getString(L, -1));
- if (it.ammoType == AMMO_NONE) {
- std::cout << "[Warning - Items::parseItemNodeLua] Unknown ammoType: " << g_lua.getString(L, -1) << std::endl;
- }
- }
- else if (lkey == "shoottype") {
- ShootType_t shoot = getShootType(g_lua.getString(L, -1));
- if (shoot != CONST_ANI_NONE) {
- it.shootType = shoot;
- }
- else {
- std::cout << "[Warning - Items::parseItemNodeLua] Unknown shootType: " << g_lua.getString(L, -1) << std::endl;
- }
- }
- else if (lkey == "effect") {
- MagicEffectClasses effect = getMagicEffect(g_lua.getString(L, -1));
- if (effect != CONST_ME_NONE) {
- it.magicEffect = effect;
- }
- else {
- std::cout << "[Warning - Items::parseItemNodeLua] Unknown effect: " << g_lua.getString(L, -1) << std::endl;
- }
- }
- else if (lkey == "range") {
- it.shootRange = g_lua.getNumber<uint16_t>(L, -1);
- }
- else if (lkey == "stopduration") {
- it.stopTime = g_lua.getBoolean(L, -1);
- }
- else if (lkey == "decayto") {
- it.decayTo = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "attackspeed") {
- it.attackspeed = g_lua.getNumber<uint32_t>(L, -1);
- }
- else if (lkey == "transformequipto") {
- it.transformEquipTo = g_lua.getNumber<uint16_t>(L, -1);
- }
- else if (lkey == "transformdeequipto") {
- it.transformDeEquipTo = g_lua.getNumber<uint16_t>(L, -1);
- }
- else if (lkey == "duration") {
- it.decayTime = g_lua.getNumber<uint32_t>(L, -1);
- }
- else if (lkey == "showduration") {
- it.showDuration = g_lua.getBoolean(L, -1);
- }
- else if (lkey == "charges") {
- it.charges = g_lua.getNumber<uint32_t>(L, -1);
- }
- else if (lkey == "showcharges") {
- it.showCharges = g_lua.getBoolean(L, -1);
- }
- else if (lkey == "showattributes") {
- it.showAttributes = g_lua.getBoolean(L, -1);
- }
- else if (lkey == "hitchance") {
- it.hitChance = std::min<int8_t>(100, std::max<int8_t>(-100, g_lua.getNumber<int16_t>(L, -1)));
- }
- else if (lkey == "maxhitchance") {
- it.maxHitChance = std::min<uint32_t>(100, g_lua.getNumber<uint32_t>(L, -1));
- }
- else if (lkey == "invisible") {
- it.getAbilities().invisible = g_lua.getBoolean(L, -1);
- }
- else if (lkey == "speed") {
- it.getAbilities().speed = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "healthgain") {
- Abilities& abilities = it.getAbilities();
- abilities.regeneration = true;
- abilities.healthGain = g_lua.getNumber<uint32_t>(L, -1);
- }
- else if (lkey == "healthticks") {
- Abilities& abilities = it.getAbilities();
- abilities.regeneration = true;
- abilities.healthTicks = g_lua.getNumber<uint32_t>(L, -1);
- }
- else if (lkey == "managain") {
- Abilities& abilities = it.getAbilities();
- abilities.regeneration = true;
- abilities.manaGain = g_lua.getNumber<uint32_t>(L, -1);
- }
- else if (lkey == "manaticks") {
- Abilities& abilities = it.getAbilities();
- abilities.regeneration = true;
- abilities.manaTicks = g_lua.getNumber<uint32_t>(L, -1);
- }
- else if (lkey == "manashield") {
- it.getAbilities().manaShield = g_lua.getBoolean(L, -1);
- }
- else if (lkey == "skillsword") {
- it.getAbilities().skills[SKILL_SWORD] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "skillaxe") {
- it.getAbilities().skills[SKILL_AXE] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "skillclub") {
- it.getAbilities().skills[SKILL_CLUB] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "skilldist") {
- it.getAbilities().skills[SKILL_DISTANCE] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "skillfish") {
- it.getAbilities().skills[SKILL_FISHING] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "skillshield") {
- it.getAbilities().skills[SKILL_SHIELD] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "skillfist") {
- it.getAbilities().skills[SKILL_FIST] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "critchance") {
- it.getAbilities().skills[SKILL_CRITICAL_HIT_CHANCE] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "critdamage") {
- it.getAbilities().skills[SKILL_CRITICAL_HIT_DAMAGE] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "lifeleechchance") {
- it.getAbilities().skills[SKILL_LIFE_LEECH_CHANCE] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "lifeleechamount") {
- it.getAbilities().skills[SKILL_LIFE_LEECH_AMOUNT] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "manaleechchance") {
- it.getAbilities().skills[SKILL_MANA_LEECH_CHANCE] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "manaleechamount") {
- it.getAbilities().skills[SKILL_MANA_LEECH_AMOUNT] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "maxhitpoints") {
- it.getAbilities().stats[STAT_MAXHITPOINTS] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "maxhitpointspercent") {
- it.getAbilities().statsPercent[STAT_MAXHITPOINTS] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "maxmanapoints") {
- it.getAbilities().stats[STAT_MAXMANAPOINTS] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "maxmanapointspercent") {
- it.getAbilities().statsPercent[STAT_MAXMANAPOINTS] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "magicpoints" || lkey == "magiclevelpoints") {
- it.getAbilities().stats[STAT_MAGICPOINTS] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "magicpointspercent") {
- it.getAbilities().statsPercent[STAT_MAGICPOINTS] = g_lua.getNumber<int32_t>(L, -1);
- }
- else if (lkey == "fieldabsorbpercentenergy") {
- it.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += g_lua.getNumber<int16_t>(L, -1);
- }
- else if (lkey == "fieldabsorbpercentfire") {
- it.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += g_lua.getNumber<int16_t>(L, -1);
- }
- else if (lkey == "fieldabsorbpercentpoison" || lkey == "fieldabsorpercentearth") {
- it.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += g_lua.getNumber<int16_t>(L, -1);
- }
- else if (lkey == "absorbpercentall" || lkey == "absorbpercentallelements") {
- int16_t value = g_lua.getNumber<int16_t>(L, -1);
- Abilities& abilities = it.getAbilities();
- for (size_t i = 0; i < COMBAT_COUNT; ++i) {
- abilities.absorbPercent[i] += value;
- }
- }
- else if (lkey == "reflectpercentall" || lkey == "reflectpercentallelements") {
- int16_t value = g_lua.getNumber<int16_t>(L, -1);
- Abilities& abilities = it.getAbilities();
- for (size_t i = 0; i < COMBAT_COUNT; i++) {
- abilities.reflectPercent[i] += value;
- }
- }
- else if (lkey == "reflectbpercentelements") {
- int16_t value = g_lua.getNumber<int16_t>(L, -1);
- Abilities& abilities = it.getAbilities();
- abilities.reflectPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += value;
- }
- else if (lkey == "reflectpercentmagic") {
- int16_t value = g_lua.getNumber<int16_t>(L, -1);
- Abilities& abilities = it.getAbilities();
- abilities.reflectPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_HOLYDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_DEATHDAMAGE)] += value;
- }
- else if (lkey == "absorbpercentelements") {
- int16_t value = g_lua.getNumber<int16_t>(L, -1);
- Abilities& abilities = it.getAbilities();
- abilities.absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += value;
- }
- else if (lkey == "absorbpercentmagic") {
- int16_t value = g_lua.getNumber<int16_t>(L, -1);
- Abilities& abilities = it.getAbilities();
- abilities.absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_HOLYDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_DEATHDAMAGE)] += value;
- }
- else if (absorbTypes[lkey]) {
- it.getAbilities().absorbPercent[combatTypeToIndex(absorbTypes[lkey])] += g_lua.getNumber<int16_t>(L, -1);
- }
- else if (reflectTypes[lkey]) {
- it.getAbilities().reflectPercent[combatTypeToIndex(reflectTypes[lkey])] += g_lua.getNumber<int16_t>(L, -1);
- }
- else if (lkey == "suppressdrunk") {
- if (g_lua.getBoolean(L, -1)) {
- it.getAbilities().conditionSuppressions |= CONDITION_DRUNK;
- }
- }
- else if (lkey == "suppressenergy") {
- if (g_lua.getBoolean(L, -1)) {
- it.getAbilities().conditionSuppressions |= CONDITION_ENERGY;
- }
- }
- else if (lkey == "suppressfire") {
- if (g_lua.getBoolean(L, -1)) {
- it.getAbilities().conditionSuppressions |= CONDITION_FIRE;
- }
- }
- else if (lkey == "suppresspoison") {
- if (g_lua.getBoolean(L, -1)) {
- it.getAbilities().conditionSuppressions |= CONDITION_POISON;
- }
- }
- else if (lkey == "suppressdrown") {
- if (g_lua.getBoolean(L, -1)) {
- it.getAbilities().conditionSuppressions |= CONDITION_DROWN;
- }
- }
- else if (lkey == "suppressphysical") {
- if (g_lua.getBoolean(L, -1)) {
- it.getAbilities().conditionSuppressions |= CONDITION_BLEEDING;
- }
- }
- else if (lkey == "suppressfreeze") {
- if (g_lua.getBoolean(L, -1)) {
- it.getAbilities().conditionSuppressions |= CONDITION_FREEZING;
- }
- }
- else if (lkey == "suppressdazzle") {
- if (g_lua.getBoolean(L, -1)) {
- it.getAbilities().conditionSuppressions |= CONDITION_DAZZLED;
- }
- }
- else if (lkey == "suppresscurse") {
- if (g_lua.getBoolean(L, -1)) {
- it.getAbilities().conditionSuppressions |= CONDITION_CURSED;
- }
- }
- else if (lkey == "field") {
- it.group = ITEM_GROUP_MAGICFIELD;
- it.type = ITEM_TYPE_MAGICFIELD;
- tmpStrValue = asLowerCaseString(g_lua.getString(L, -1));
- if (!conTypes[tmpStrValue]) {
- std::cout << "[Warning - Items::parseItemNodeLua] Unknown field value: " << tmpStrValue << std::endl;
- }
- else {
- combatType = comTypes[conTypes[tmpStrValue]];
- }
- }
- // eliminate setting damage in the sources for now
- else if (lkey == "replaceable") {
- it.replaceable = g_lua.getBoolean(L, -1);
- }
- else if (lkey == "partnerdirection") {
- it.bedPartnerDir = getDirection(g_lua.getString(L, -1));
- }
- else if (lkey == "leveldoor") {
- it.levelDoor = g_lua.getNumber<uint32_t>(L, -1);
- }
- else if (lkey == "maletransformto" || lkey == "malesleeper") {
- uint16_t value = g_lua.getNumber<uint16_t>(L, -1);
- it.transformToOnUse[PLAYERSEX_MALE] = value;
- ItemType& other = getItemType(value);
- if (other.transformToFree == 0) {
- other.transformToFree = it.id;
- }
- if (it.transformToOnUse[PLAYERSEX_FEMALE] == 0) {
- it.transformToOnUse[PLAYERSEX_FEMALE] = value;
- }
- }
- else if (lkey == "femaletransformto" || lkey == "femalesleeper") {
- uint16_t value = g_lua.getNumber<uint16_t>(L, -1);
- it.transformToOnUse[PLAYERSEX_FEMALE] = value;
- ItemType& other = getItemType(value);
- if (other.transformToFree == 0) {
- other.transformToFree = it.id;
- }
- if (it.transformToOnUse[PLAYERSEX_MALE] == 0) {
- it.transformToOnUse[PLAYERSEX_MALE] = value;
- }
- }
- else if (lkey == "transformto") {
- it.transformToFree = g_lua.getNumber<uint16_t>(L, -1);
- }
- else if (lkey == "destroyto") {
- it.destroyTo = g_lua.getNumber<uint16_t>(L, -1);
- }
- else if (lkey == "elementice") {
- Abilities& abilities = it.getAbilities();
- abilities.elementDamage = g_lua.getNumber<uint16_t>(L, -1);
- abilities.elementType = COMBAT_ICEDAMAGE;
- }
- else if (lkey == "elementearth") {
- Abilities& abilities = it.getAbilities();
- abilities.elementDamage = g_lua.getNumber<uint16_t>(L, -1);
- abilities.elementType = COMBAT_EARTHDAMAGE;
- }
- else if (lkey == "elementfire") {
- Abilities& abilities = it.getAbilities();
- abilities.elementDamage = g_lua.getNumber<uint16_t>(L, -1);
- abilities.elementType = COMBAT_FIREDAMAGE;
- }
- else if (lkey == "elementenergy") {
- Abilities& abilities = it.getAbilities();
- abilities.elementDamage = g_lua.getNumber<uint16_t>(L, -1);
- abilities.elementType = COMBAT_ENERGYDAMAGE;
- }
- else if (lkey == "elementdeath") {
- Abilities& abilities = it.getAbilities();
- abilities.elementDamage = g_lua.getNumber<uint16_t>(L, -1);
- abilities.elementType = COMBAT_DEATHDAMAGE;
- }
- else if (lkey == "elementholy") {
- Abilities& abilities = it.getAbilities();
- abilities.elementDamage = g_lua.getNumber<uint16_t>(L, -1);
- abilities.elementType = COMBAT_HOLYDAMAGE;
- }
- else if (lkey == "walkstack") {
- it.walkStack = g_lua.getBoolean(L, -1);
- }
- else if (lkey == "blocking") {
- it.blockSolid = g_lua.getBoolean(L, -1);
- }
- else if (lkey == "allowdistread") {
- it.allowDistRead = booleanString(g_lua.getString(L, -1));
- }
- else {
- std::cout << "[Warning - Items::parseItemNodeLua] Unknown key value: " << lkey << std::endl;
- }
- }// end of value
- //check bed items
- if ((it.transformToFree != 0 || it.transformToOnUse[PLAYERSEX_FEMALE] != 0 || it.transformToOnUse[PLAYERSEX_MALE] != 0) && it.type != ITEM_TYPE_BED) {
- //std::cout << "[Warning - Items::parseItemNodeLua] Item " << it.id << " is not set as a bed-type" << std::endl;
- }//
- lua_pop(L, 1);
- }// end of inner for loop
- lua_pop(L, 1);
- }
- }// end of objlen
- }// end of attributes
- lua_pop(L, 1);
- break;
- } // end of outter switch
- lua_pop(L, 1);
- }//end of outter loop
- }
- // this function not only parses the items.xml but it also can construct items.xml in a lua table
- void Items::parseItemNode(const pugi::xml_node& itemNode, uint16_t id, std::ofstream& out, bool constructTable)
- {
- bool description = false, field = false;
- std::string parser, pattribute, desc, key, pfield = "";
- if (constructTable) {
- parser = "\t{\n\t\titemid = " + std::to_string(id) + ", ";
- }
- if (id > 30000 && id < 30100) {
- id -= 30000;
- if (id >= items.size()) {
- items.resize(id + 1);
- }
- ItemType& iType = items[id];
- iType.id = id;
- }
- ItemType& it = getItemType(id);
- if (it.id == 0) {
- return;
- }
- it.name = itemNode.attribute("name").as_string();
- if (constructTable) {
- parser += "name = \"" + it.name + "\", ";
- }
- pugi::xml_attribute articleAttribute = itemNode.attribute("article");
- if (articleAttribute) {
- it.article = articleAttribute.as_string();
- if (constructTable) {
- parser += "article = \"" + it.article + "\", ";
- }
- }
- pugi::xml_attribute pluralAttribute = itemNode.attribute("plural");
- if (pluralAttribute) {
- it.pluralName = pluralAttribute.as_string();
- if (constructTable) {
- parser += "plural = \"" + it.pluralName + "\", ";
- }
- }
- for (auto attributeNode : itemNode.children()) {
- pugi::xml_attribute keyAttribute = attributeNode.attribute("key");
- if (!keyAttribute) {
- continue;
- }
- if (constructTable) {
- key = asLowerCaseString(keyAttribute.as_string());
- if (key == "description")
- {
- description = true;
- }
- //out << "\t\t\t{ key = \"" << key << "\", ";
- if (key == "field") {
- field = true;
- //pfield += "\t\t\t{ key = \"" + key + "\", ";
- }
- else {
- pattribute += "\t\t\t{ key = \"" + key + "\", ";
- }
- }
- pugi::xml_attribute valueAttribute = attributeNode.attribute("value");
- if (!valueAttribute) {
- continue;
- }
- if (constructTable) {
- desc = valueAttribute.as_string();
- if (description) {
- desc = alterString(desc, "\"", "'");
- }
- //out << "value = \"" << desc << "\" },\n";
- if (field) {
- //pfield += "value = \"" + desc + "\" },\n";
- }
- else {
- pattribute += "value = \"" + desc + "\" },\n";
- }
- }
- std::string tmpStrValue = asLowerCaseString(keyAttribute.as_string());
- if (tmpStrValue == "type") {
- tmpStrValue = asLowerCaseString(valueAttribute.as_string());
- if (tmpStrValue == "key") {
- it.type = ITEM_TYPE_KEY;
- }
- else if (tmpStrValue == "magicfield") {
- it.type = ITEM_TYPE_MAGICFIELD;
- }
- else if (tmpStrValue == "container") {
- it.group = ITEM_GROUP_CONTAINER;
- it.type = ITEM_TYPE_CONTAINER;
- }
- else if (tmpStrValue == "depot") {
- it.type = ITEM_TYPE_DEPOT;
- }
- else if (tmpStrValue == "rewardchest") {
- it.type = ITEM_TYPE_REWARDCHEST;
- }
- else if (tmpStrValue == "mailbox") {
- it.type = ITEM_TYPE_MAILBOX;
- }
- else if (tmpStrValue == "trashholder") {
- it.type = ITEM_TYPE_TRASHHOLDER;
- }
- else if (tmpStrValue == "teleport") {
- it.type = ITEM_TYPE_TELEPORT;
- }
- else if (tmpStrValue == "door") {
- it.type = ITEM_TYPE_DOOR;
- }
- else if (tmpStrValue == "bed") {
- it.type = ITEM_TYPE_BED;
- }
- else if (tmpStrValue == "rune") {
- it.type = ITEM_TYPE_RUNE;
- }
- else {
- std::cout << "[Warning - Items::parseItemNode] Unknown type: " << valueAttribute.as_string() << std::endl;
- }
- }
- else if (tmpStrValue == "description") {
- it.description = valueAttribute.as_string();
- }
- else if (tmpStrValue == "runespellname") {
- it.runeSpellName = valueAttribute.as_string();
- }
- else if (tmpStrValue == "weight") {
- it.weight = pugi::cast<uint32_t>(valueAttribute.value());
- }// custom added
- else if (tmpStrValue == "tier") {
- it.tier = pugi::cast<uint32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "power") {
- it.power = pugi::cast<uint32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "heal") {
- it.heal = pugi::cast<uint32_t>(valueAttribute.value());
- }// custom added
- else if (tmpStrValue == "showcount") {
- it.showCount = valueAttribute.as_bool();
- }
- else if (tmpStrValue == "armor") {
- it.armor = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "defense") {
- it.defense = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "extradef") {
- it.extraDefense = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "attack") {
- it.attack = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "rotateto") {
- it.rotateTo = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "moveable" || tmpStrValue == "movable") {
- it.moveable = valueAttribute.as_bool();
- }
- else if (tmpStrValue == "blockprojectile") {
- it.blockProjectile = valueAttribute.as_bool();
- }
- else if (tmpStrValue == "allowpickupable" || tmpStrValue == "pickupable") {
- it.allowPickupable = valueAttribute.as_bool();
- }
- else if (tmpStrValue == "floorchange") {
- tmpStrValue = asLowerCaseString(valueAttribute.as_string());
- if (tmpStrValue == "down") {
- it.floorChange = TILESTATE_FLOORCHANGE_DOWN;
- }
- else if (tmpStrValue == "north") {
- it.floorChange = TILESTATE_FLOORCHANGE_NORTH;
- }
- else if (tmpStrValue == "south") {
- it.floorChange = TILESTATE_FLOORCHANGE_SOUTH;
- }
- else if (tmpStrValue == "southalt") {
- it.floorChange = TILESTATE_FLOORCHANGE_SOUTH_ALT;
- }
- else if (tmpStrValue == "west") {
- it.floorChange = TILESTATE_FLOORCHANGE_WEST;
- }
- else if (tmpStrValue == "east") {
- it.floorChange = TILESTATE_FLOORCHANGE_EAST;
- }
- else if (tmpStrValue == "eastalt") {
- it.floorChange = TILESTATE_FLOORCHANGE_EAST_ALT;
- }
- else {
- std::cout << "[Warning - Items::parseItemNode] Unknown floorChange: " << valueAttribute.as_string() << std::endl;
- }
- }
- else if (tmpStrValue == "corpsetype") {
- tmpStrValue = asLowerCaseString(valueAttribute.as_string());
- if (tmpStrValue == "venom") {
- it.corpseType = RACE_VENOM;
- }
- else if (tmpStrValue == "blood") {
- it.corpseType = RACE_BLOOD;
- }
- else if (tmpStrValue == "undead") {
- it.corpseType = RACE_UNDEAD;
- }
- else if (tmpStrValue == "fire") {
- it.corpseType = RACE_FIRE;
- }
- else if (tmpStrValue == "energy") {
- it.corpseType = RACE_ENERGY;
- }
- else {
- std::cout << "[Warning - Items::parseItemNode] Unknown corpseType: " << valueAttribute.as_string() << std::endl;
- }
- }
- else if (tmpStrValue == "containersize") {
- it.maxItems = pugi::cast<uint16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "fluidsource") {
- tmpStrValue = asLowerCaseString(valueAttribute.as_string());
- if (tmpStrValue == "water") {
- it.fluidSource = FLUID_WATER;
- }
- else if (tmpStrValue == "blood") {
- it.fluidSource = FLUID_BLOOD;
- }
- else if (tmpStrValue == "beer") {
- it.fluidSource = FLUID_BEER;
- }
- else if (tmpStrValue == "slime") {
- it.fluidSource = FLUID_SLIME;
- }
- else if (tmpStrValue == "lemonade") {
- it.fluidSource = FLUID_LEMONADE;
- }
- else if (tmpStrValue == "milk") {
- it.fluidSource = FLUID_MILK;
- }
- else if (tmpStrValue == "mana") {
- it.fluidSource = FLUID_MANA;
- }
- else if (tmpStrValue == "life") {
- it.fluidSource = FLUID_LIFE;
- }
- else if (tmpStrValue == "oil") {
- it.fluidSource = FLUID_OIL;
- }
- else if (tmpStrValue == "urine") {
- it.fluidSource = FLUID_URINE;
- }
- else if (tmpStrValue == "coconut") {
- it.fluidSource = FLUID_COCONUTMILK;
- }
- else if (tmpStrValue == "wine") {
- it.fluidSource = FLUID_WINE;
- }
- else if (tmpStrValue == "mud") {
- it.fluidSource = FLUID_MUD;
- }
- else if (tmpStrValue == "fruitjuice") {
- it.fluidSource = FLUID_FRUITJUICE;
- }
- else if (tmpStrValue == "lava") {
- it.fluidSource = FLUID_LAVA;
- }
- else if (tmpStrValue == "rum") {
- it.fluidSource = FLUID_RUM;
- }
- else if (tmpStrValue == "swamp") {
- it.fluidSource = FLUID_SWAMP;
- }
- else if (tmpStrValue == "tea") {
- it.fluidSource = FLUID_TEA;
- }
- else if (tmpStrValue == "mead") {
- it.fluidSource = FLUID_MEAD;
- }
- else {
- std::cout << "[Warning - Items::parseItemNode] Unknown fluidSource: " << valueAttribute.as_string() << std::endl;
- }
- }
- else if (tmpStrValue == "readable") {
- it.canReadText = valueAttribute.as_bool();
- }
- else if (tmpStrValue == "writeable") {
- it.canWriteText = valueAttribute.as_bool();
- it.canReadText = it.canWriteText;
- }
- else if (tmpStrValue == "maxtextlen") {
- it.maxTextLen = pugi::cast<uint16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "writeonceitemid") {
- it.writeOnceItemId = pugi::cast<uint16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "weapontype") {
- tmpStrValue = asLowerCaseString(valueAttribute.as_string());
- if (tmpStrValue == "sword") {
- it.weaponType = WEAPON_SWORD;
- }
- else if (tmpStrValue == "club") {
- it.weaponType = WEAPON_CLUB;
- }
- else if (tmpStrValue == "axe") {
- it.weaponType = WEAPON_AXE;
- }
- else if (tmpStrValue == "shield") {
- it.weaponType = WEAPON_SHIELD;
- }
- else if (tmpStrValue == "distance") {
- it.weaponType = WEAPON_DISTANCE;
- }
- else if (tmpStrValue == "wand") {
- it.weaponType = WEAPON_WAND;
- }
- else if (tmpStrValue == "ammunition") {
- it.weaponType = WEAPON_AMMO;
- }
- else if (tmpStrValue == "fist") {
- it.weaponType = WEAPON_FIST;
- }
- else {
- std::cout << "[Warning - Items::parseItemNode] Unknown weaponType: " << valueAttribute.as_string() << std::endl;
- }
- }
- else if (tmpStrValue == "slottype") {
- tmpStrValue = asLowerCaseString(valueAttribute.as_string());
- if (tmpStrValue == "head") {
- it.slotPosition |= SLOTP_HEAD;
- }
- else if (tmpStrValue == "body") {
- it.slotPosition |= SLOTP_ARMOR;
- }
- else if (tmpStrValue == "legs") {
- it.slotPosition |= SLOTP_LEGS;
- }
- else if (tmpStrValue == "feet") {
- it.slotPosition |= SLOTP_FEET;
- }
- else if (tmpStrValue == "backpack") {
- it.slotPosition |= SLOTP_BACKPACK;
- }
- else if (tmpStrValue == "two-handed") {
- it.slotPosition |= SLOTP_TWO_HAND;
- }
- else if (tmpStrValue == "right-hand") {
- it.slotPosition &= ~SLOTP_LEFT;
- }
- else if (tmpStrValue == "left-hand") {
- it.slotPosition &= ~SLOTP_RIGHT;
- }
- else if (tmpStrValue == "necklace") {
- it.slotPosition |= SLOTP_NECKLACE;
- }
- else if (tmpStrValue == "ring") {
- it.slotPosition |= SLOTP_RING;
- }
- else if (tmpStrValue == "ammo") {
- it.slotPosition |= SLOTP_AMMO;
- }
- else if (tmpStrValue == "hand") {
- it.slotPosition |= SLOTP_HAND;
- }
- else {
- std::cout << "[Warning - Items::parseItemNode] Unknown slotType: " << valueAttribute.as_string() << std::endl;
- }
- }
- else if (tmpStrValue == "ammotype") {
- it.ammoType = getAmmoType(valueAttribute.as_string());
- if (it.ammoType == AMMO_NONE) {
- std::cout << "[Warning - Items::parseItemNode] Unknown ammoType: " << valueAttribute.as_string() << std::endl;
- }
- }
- else if (tmpStrValue == "shoottype") {
- ShootType_t shoot = getShootType(valueAttribute.as_string());
- if (shoot != CONST_ANI_NONE) {
- it.shootType = shoot;
- }
- else {
- std::cout << "[Warning - Items::parseItemNode] Unknown shootType: " << valueAttribute.as_string() << std::endl;
- }
- }
- else if (tmpStrValue == "effect") {
- MagicEffectClasses effect = getMagicEffect(valueAttribute.as_string());
- if (effect != CONST_ME_NONE) {
- it.magicEffect = effect;
- }
- else {
- std::cout << "[Warning - Items::parseItemNode] Unknown effect: " << valueAttribute.as_string() << std::endl;
- }
- }
- else if (tmpStrValue == "range") {
- it.shootRange = pugi::cast<uint16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "stopduration") {
- it.stopTime = valueAttribute.as_bool();
- }
- else if (tmpStrValue == "decayto") {
- it.decayTo = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "transformequipto") {
- it.transformEquipTo = pugi::cast<uint16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "transformdeequipto") {
- it.transformDeEquipTo = pugi::cast<uint16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "duration") {
- it.decayTime = pugi::cast<uint32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "showduration") {
- it.showDuration = valueAttribute.as_bool();
- }
- else if (tmpStrValue == "charges") {
- it.charges = pugi::cast<uint32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "showcharges") {
- it.showCharges = valueAttribute.as_bool();
- }
- else if (tmpStrValue == "showattributes") {
- it.showAttributes = valueAttribute.as_bool();
- }
- else if (tmpStrValue == "hitchance") {
- it.hitChance = std::min<int8_t>(100, std::max<int8_t>(-100, pugi::cast<int16_t>(valueAttribute.value())));
- }
- else if (tmpStrValue == "maxhitchance") {
- it.maxHitChance = std::min<uint32_t>(100, pugi::cast<uint32_t>(valueAttribute.value()));
- }
- else if (tmpStrValue == "invisible") {
- it.getAbilities().invisible = valueAttribute.as_bool();
- }
- else if (tmpStrValue == "speed") {
- it.getAbilities().speed = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "healthgain") {
- Abilities& abilities = it.getAbilities();
- abilities.regeneration = true;
- abilities.healthGain = pugi::cast<uint32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "healthticks") {
- Abilities& abilities = it.getAbilities();
- abilities.regeneration = true;
- abilities.healthTicks = pugi::cast<uint32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "managain") {
- Abilities& abilities = it.getAbilities();
- abilities.regeneration = true;
- abilities.manaGain = pugi::cast<uint32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "manaticks") {
- Abilities& abilities = it.getAbilities();
- abilities.regeneration = true;
- abilities.manaTicks = pugi::cast<uint32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "manashield") {
- it.getAbilities().manaShield = valueAttribute.as_bool();
- }
- else if (tmpStrValue == "skillsword") {
- it.getAbilities().skills[SKILL_SWORD] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "skillaxe") {
- it.getAbilities().skills[SKILL_AXE] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "skillclub") {
- it.getAbilities().skills[SKILL_CLUB] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "skilldist") {
- it.getAbilities().skills[SKILL_DISTANCE] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "skillfish") {
- it.getAbilities().skills[SKILL_FISHING] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "skillshield") {
- it.getAbilities().skills[SKILL_SHIELD] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "skillfist") {
- it.getAbilities().skills[SKILL_FIST] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "skillcriticalchance") {
- it.getAbilities().skills[SKILL_CRITICAL_HIT_CHANCE] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "skillcriticaldamage") {
- it.getAbilities().skills[SKILL_CRITICAL_HIT_DAMAGE] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "skilllifechance") {
- it.getAbilities().skills[SKILL_LIFE_LEECH_CHANCE] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "skilllifeamount") {
- it.getAbilities().skills[SKILL_LIFE_LEECH_AMOUNT] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "skillmanachance") {
- it.getAbilities().skills[SKILL_MANA_LEECH_CHANCE] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "skillmanaamount") {
- it.getAbilities().skills[SKILL_MANA_LEECH_AMOUNT] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "maxhitpoints") {
- it.getAbilities().stats[STAT_MAXHITPOINTS] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "maxhitpointspercent") {
- it.getAbilities().statsPercent[STAT_MAXHITPOINTS] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "maxmanapoints") {
- it.getAbilities().stats[STAT_MAXMANAPOINTS] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "maxmanapointspercent") {
- it.getAbilities().statsPercent[STAT_MAXMANAPOINTS] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "magicpoints" || tmpStrValue == "magiclevelpoints") {
- it.getAbilities().stats[STAT_MAGICPOINTS] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "magicpointspercent") {
- it.getAbilities().statsPercent[STAT_MAGICPOINTS] = pugi::cast<int32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "fieldabsorbpercentenergy") {
- it.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "fieldabsorbpercentfire") {
- it.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "fieldabsorbpercentpoison" || tmpStrValue == "fieldabsorpercentearth") {
- it.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "absorbpercentall" || tmpStrValue == "absorbpercentallelements") {
- int16_t value = pugi::cast<int16_t>(valueAttribute.value());
- Abilities& abilities = it.getAbilities();
- for (size_t i = 0; i < COMBAT_COUNT; ++i) {
- abilities.absorbPercent[i] += value;
- }
- }
- else if (tmpStrValue == "reflectpercentall" || tmpStrValue == "reflectpercentallelements") {
- int16_t value = pugi::cast<int16_t>(valueAttribute.value());
- Abilities& abilities = it.getAbilities();
- for (size_t i = 0; i < COMBAT_COUNT; i++) {
- abilities.reflectPercent[i] += value;
- }
- }
- else if (tmpStrValue == "reflectbpercentelements") {
- int16_t value = pugi::cast<int16_t>(valueAttribute.value());
- Abilities& abilities = it.getAbilities();
- abilities.reflectPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += value;
- }
- else if (tmpStrValue == "reflectpercentmagic") {
- int16_t value = pugi::cast<int16_t>(valueAttribute.value());
- Abilities& abilities = it.getAbilities();
- abilities.reflectPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_HOLYDAMAGE)] += value;
- abilities.reflectPercent[combatTypeToIndex(COMBAT_DEATHDAMAGE)] += value;
- }
- else if (tmpStrValue == "absorbpercentelements") {
- int16_t value = pugi::cast<int16_t>(valueAttribute.value());
- Abilities& abilities = it.getAbilities();
- abilities.absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += value;
- }
- else if (tmpStrValue == "absorbpercentmagic") {
- int16_t value = pugi::cast<int16_t>(valueAttribute.value());
- Abilities& abilities = it.getAbilities();
- abilities.absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_HOLYDAMAGE)] += value;
- abilities.absorbPercent[combatTypeToIndex(COMBAT_DEATHDAMAGE)] += value;
- }
- else if (tmpStrValue == "absorbpercentenergy") {
- it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "absorbpercentfire") {
- it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "absorbpercentpoison" || tmpStrValue == "absorbpercentearth") {
- it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "absorbpercentice") {
- it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "absorbpercentholy") {
- it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_HOLYDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "absorbpercentdeath") {
- it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_DEATHDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "absorbpercentlifedrain") {
- it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_LIFEDRAIN)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "absorbpercentmanadrain") {
- it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_MANADRAIN)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "absorbpercentdrown") {
- it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_DROWNDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "absorbpercentphysical") {
- it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_PHYSICALDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "absorbpercenthealing") {
- it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_HEALING)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "reflectpercentenergy") {
- it.getAbilities().reflectPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "reflectpercentfire") {
- it.getAbilities().reflectPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "reflectpercentpoison" || tmpStrValue == "reflectpercentearth") {
- it.getAbilities().reflectPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "reflectpercentice") {
- it.getAbilities().reflectPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "reflectpercentholy") {
- it.getAbilities().reflectPercent[combatTypeToIndex(COMBAT_HOLYDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "reflectpercentdeath") {
- it.getAbilities().reflectPercent[combatTypeToIndex(COMBAT_DEATHDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "reflectpercentlifedrain") {
- it.getAbilities().reflectPercent[combatTypeToIndex(COMBAT_LIFEDRAIN)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "reflectpercentmanadrain") {
- it.getAbilities().reflectPercent[combatTypeToIndex(COMBAT_MANADRAIN)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "reflectpercentphysical") {
- it.getAbilities().reflectPercent[combatTypeToIndex(COMBAT_PHYSICALDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "suppressdrunk") {
- if (valueAttribute.as_bool()) {
- it.getAbilities().conditionSuppressions |= CONDITION_DRUNK;
- }
- }
- else if (tmpStrValue == "suppressenergy") {
- if (valueAttribute.as_bool()) {
- it.getAbilities().conditionSuppressions |= CONDITION_ENERGY;
- }
- }
- else if (tmpStrValue == "suppressfire") {
- if (valueAttribute.as_bool()) {
- it.getAbilities().conditionSuppressions |= CONDITION_FIRE;
- }
- }
- else if (tmpStrValue == "suppresspoison") {
- if (valueAttribute.as_bool()) {
- it.getAbilities().conditionSuppressions |= CONDITION_POISON;
- }
- }
- else if (tmpStrValue == "suppressdrown") {
- if (valueAttribute.as_bool()) {
- it.getAbilities().conditionSuppressions |= CONDITION_DROWN;
- }
- }
- else if (tmpStrValue == "suppressphysical") {
- if (valueAttribute.as_bool()) {
- it.getAbilities().conditionSuppressions |= CONDITION_BLEEDING;
- }
- }
- else if (tmpStrValue == "suppressfreeze") {
- if (valueAttribute.as_bool()) {
- it.getAbilities().conditionSuppressions |= CONDITION_FREEZING;
- }
- }
- else if (tmpStrValue == "suppressdazzle") {
- if (valueAttribute.as_bool()) {
- it.getAbilities().conditionSuppressions |= CONDITION_DAZZLED;
- }
- }
- else if (tmpStrValue == "suppresscurse") {
- if (valueAttribute.as_bool()) {
- it.getAbilities().conditionSuppressions |= CONDITION_CURSED;
- }
- }
- else if (tmpStrValue == "field") {
- it.group = ITEM_GROUP_MAGICFIELD;
- it.type = ITEM_TYPE_MAGICFIELD;
- std::string constr;
- CombatType_t combatType = COMBAT_NONE;
- ConditionDamage* conditionDamage = nullptr;
- constr = asLowerCaseString(valueAttribute.as_string());
- tmpStrValue = constr;
- if (tmpStrValue == "fire") {
- conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_FIRE);
- combatType = COMBAT_FIREDAMAGE;
- }
- else if (tmpStrValue == "energy") {
- conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_ENERGY);
- combatType = COMBAT_ENERGYDAMAGE;
- }
- else if (tmpStrValue == "poison") {
- conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_POISON);
- combatType = COMBAT_EARTHDAMAGE;
- }
- else if (tmpStrValue == "drown") {
- conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_DROWN);
- combatType = COMBAT_DROWNDAMAGE;
- }
- else if (tmpStrValue == "physical") {
- conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_BLEEDING);
- combatType = COMBAT_PHYSICALDAMAGE;
- }
- else {
- std::cout << "[Warning - Items::parseItemNode] Unknown field value: " << valueAttribute.as_string() << std::endl;
- }
- if (combatType != COMBAT_NONE) {
- it.combatType = combatType;
- it.conditionDamage.reset(conditionDamage);
- uint32_t ticks = 0;
- int32_t damage = 0;
- int32_t start = 0;
- int32_t count = 1;
- for (auto subAttributeNode : attributeNode.children()) {
- pugi::xml_attribute subKeyAttribute = subAttributeNode.attribute("key");
- if (!subKeyAttribute) {
- continue;
- }
- if (constructTable) {
- std::string skey = asLowerCaseString(subKeyAttribute.as_string());
- }
- pugi::xml_attribute subValueAttribute = subAttributeNode.attribute("value");
- if (!subValueAttribute) {
- continue;
- }
- if (constructTable) {
- std::string svalue = subValueAttribute.as_string();
- }
- tmpStrValue = asLowerCaseString(subKeyAttribute.as_string());
- if (tmpStrValue == "ticks") {
- ticks = pugi::cast<uint32_t>(subValueAttribute.value());
- }
- else if (tmpStrValue == "count") {
- count = std::max<int32_t>(1, pugi::cast<int32_t>(subValueAttribute.value()));
- }
- else if (tmpStrValue == "start") {
- start = std::max<int32_t>(0, pugi::cast<int32_t>(subValueAttribute.value()));
- }
- else if (tmpStrValue == "damage") {
- damage = -pugi::cast<int32_t>(subValueAttribute.value());
- if (start > 0) {
- std::list<int32_t> damageList;
- ConditionDamage::generateDamageList(damage, start, damageList);
- for (int32_t damageValue : damageList) {
- conditionDamage->addDamage(1, ticks, -damageValue);
- }
- start = 0;
- }
- else {
- conditionDamage->addDamage(count, ticks, damage);
- }
- }
- }
- conditionDamage->setParam(CONDITION_PARAM_FIELD, 1);
- if (conditionDamage->getTotalDamage() > 0) {
- conditionDamage->setParam(CONDITION_PARAM_FORCEUPDATE, 1);
- }
- }
- }
- else if (tmpStrValue == "replaceable") {
- it.replaceable = valueAttribute.as_bool();
- }
- else if (tmpStrValue == "partnerdirection") {
- it.bedPartnerDir = getDirection(valueAttribute.as_string());
- }
- else if (tmpStrValue == "leveldoor") {
- it.levelDoor = pugi::cast<uint32_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "maletransformto" || tmpStrValue == "malesleeper") {
- uint16_t value = pugi::cast<uint16_t>(valueAttribute.value());
- it.transformToOnUse[PLAYERSEX_MALE] = value;
- ItemType& other = getItemType(value);
- if (other.transformToFree == 0) {
- other.transformToFree = it.id;
- }
- if (it.transformToOnUse[PLAYERSEX_FEMALE] == 0) {
- it.transformToOnUse[PLAYERSEX_FEMALE] = value;
- }
- }
- else if (tmpStrValue == "femaletransformto" || tmpStrValue == "femalesleeper") {
- uint16_t value = pugi::cast<uint16_t>(valueAttribute.value());
- it.transformToOnUse[PLAYERSEX_FEMALE] = value;
- ItemType& other = getItemType(value);
- if (other.transformToFree == 0) {
- other.transformToFree = it.id;
- }
- if (it.transformToOnUse[PLAYERSEX_MALE] == 0) {
- it.transformToOnUse[PLAYERSEX_MALE] = value;
- }
- }
- else if (tmpStrValue == "transformto") {
- it.transformToFree = pugi::cast<uint16_t>(valueAttribute.value());
- }
- else if (tmpStrValue == "destroyto") {
- it.destroyTo = pugi::cast<uint16_t>(valueAttribute.value());
- }
- else if (elementTypes[tmpStrValue]) {
- Abilities& abilities = it.getAbilities();
- abilities.elementDamage = pugi::cast<uint16_t>(valueAttribute.value());
- abilities.elementType = elementTypes[tmpStrValue];
- }
- /*else if (tmpStrValue == "elementearth") {
- Abilities& abilities = it.getAbilities();
- abilities.elementDamage = pugi::cast<uint16_t>(valueAttribute.value());
- abilities.elementType = COMBAT_EARTHDAMAGE;
- }
- else if (tmpStrValue == "elementfire") {
- Abilities& abilities = it.getAbilities();
- abilities.elementDamage = pugi::cast<uint16_t>(valueAttribute.value());
- abilities.elementType = COMBAT_FIREDAMAGE;
- }
- else if (tmpStrValue == "elementenergy") {
- Abilities& abilities = it.getAbilities();
- abilities.elementDamage = pugi::cast<uint16_t>(valueAttribute.value());
- abilities.elementType = COMBAT_ENERGYDAMAGE;
- }
- else if (tmpStrValue == "elementdeath") {
- Abilities& abilities = it.getAbilities();
- abilities.elementDamage = pugi::cast<uint16_t>(valueAttribute.value());
- abilities.elementType = COMBAT_DEATHDAMAGE;
- }
- else if (tmpStrValue == "elementholy") {
- Abilities& abilities = it.getAbilities();
- abilities.elementDamage = pugi::cast<uint16_t>(valueAttribute.value());
- abilities.elementType = COMBAT_HOLYDAMAGE;
- }*/
- else if (tmpStrValue == "walkstack") {
- it.walkStack = valueAttribute.as_bool();
- }
- else if (tmpStrValue == "blocking") {
- it.blockSolid = valueAttribute.as_bool();
- }
- else if (tmpStrValue == "allowdistread") {
- it.allowDistRead = booleanString(valueAttribute.as_string());
- }
- else {
- std::cout << "[Warning - Items::parseItemNode] Unknown key value: " << keyAttribute.as_string() << std::endl;
- }
- }
- if (constructTable) {
- parser += "\n\t\tattributes = {\n" + pattribute + "\t\t}\n\t},\n";
- out << parser;
- }
- //check bed items
- if ((it.transformToFree != 0 || it.transformToOnUse[PLAYERSEX_FEMALE] != 0 || it.transformToOnUse[PLAYERSEX_MALE] != 0) && it.type != ITEM_TYPE_BED) {
- std::cout << "[Warning - Items::parseItemNode] Item " << it.id << " is not set as a bed-type" << std::endl;
- }
- }
- ItemType& Items::getItemType(size_t id)
- {
- if (id < items.size()) {
- return items[id];
- }
- return items.front();
- }
- const ItemType& Items::getItemType(size_t id) const
- {
- if (id < items.size()) {
- return items[id];
- }
- return items.front();
- }
- const ItemType& Items::getItemIdByClientId(uint16_t spriteId) const
- {
- auto it = reverseItemMap.find(spriteId);
- if (it != reverseItemMap.end()) {
- return getItemType(it->second);
- }
- return items.front();
- }
- uint16_t Items::getItemIdByName(const std::string& name)
- {
- auto result = nameToItems.find(asLowerCaseString(name));
- if (result == nameToItems.end())
- return 0;
- return result->second;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement