• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Lua Function Saving map in game - creates a new otbm

Capaverde

New Member
Joined
Sep 30, 2007
Messages
107
Reaction score
4
I did it with the idea of ​​allowing players to build houses in the woods and save the houses and such

How did I do? I took the saveMap from Remere (which is open source) and modified it a bit and adapted to what OTServer has.
I tested and ran it on theforgottenserver 0.2rc9

It will create the file in the same folder where config.lua is


luascript.h:
Code:
	static int32_t luaSaveMap(lua_State* L);

luascript.cpp, inside registerFunctions():
Code:
	//saveMap()
	lua_register(m_luaState, "saveMap", LuaScriptInterface::luaSaveMap);

luascript.cpp:
Code:
int32_t LuaScriptInterface::luaSaveMap(lua_State* L)
{
    //saveMap()
    g_game.saveMapzord();
}

game.h(public):
Code:
        void saveMapzord(){map->saveMapzord();}

map.h, under bool saveMap();:

Code:
	bool saveMapzord();

map.cpp:

Code:
bool Map::saveMapzord()
{
	IOMap* loader = new IOMap();
	bool saved = false;

	for(uint32_t tries = 0; tries < 3; tries++)
	{
		if(loader->saveMap(this, "eai.otbm", false)) 
		{
			saved = true;
			break;
		}
	}
		
	return saved;
	
}

iomap.h:

Code:
		bool saveMap(Map* map, const std::string& identifier, bool showdialog);

iomap.cpp:

Code:
bool IOMap::saveMap(Map* map, const std::string& identifier, bool showdialog) {
	/* STOP!
	 * Before you even think about modifying this, please reconsider.
	 * while adding stuff to the binary format may be "cool", you'll
	 * inevitably make it incompatible with any future releases of
	 * the map editor, meaning you cannot reuse your map. Before you
	 * try to modify this, PLEASE consider using an external file
	 * like spawns.xml or houses.xml, as that will be MUCH easier
	 * to port to newer versions of the editor than a custom binary
	 * format.
	 */
	
	/*if(Items::dwMajorVersion < 3) {
		version = 0;
	} else {
		version = 1;
	}*/
	FileLoader f;
	f.openFile(identifier.c_str(), true, false);

	f.startNode(0); {
		f.addU32(0); // Version
		f.addU16((uint16_t)map->mapWidth);
		f.addU16((uint16_t)map->mapHeight);
		f.addU32(Items::dwMajorVersion);
		f.addU32(Items::dwMinorVersion);

		f.startNode(OTBM_MAP_DATA); {
			f.addByte(OTBM_ATTR_DESCRIPTION);
			// Neither SimOne's nor OpenTibia cares for additional description tags
			f.addString("Saved with Remere's Map Editor ");

			f.addU8(OTBM_ATTR_DESCRIPTION);
			f.addString("Esse mapa é maneiro.");

			/*f.addU8(OTBM_ATTR_EXT_SPAWN_FILE);
			FileName fn(wxstr(map->spawnfile));
			f.addString(std::string((const char*)fn.GetFullName().mb_str(wxConvUTF8)));
			
			if(gui.GetCurrentVersion() > CLIENT_VERSION_760) {
				f.addU8(OTBM_ATTR_EXT_HOUSE_FILE);
				fn.Assign(wxstr(map->housefile));
				f.addString(std::string((const char*)fn.GetFullName().mb_str(wxConvUTF8)));
			}*/

			// Start writing tiles
			//uint64_t tiles_saved = 0;
			bool first = true;

			int local_x = -1, local_y = -1, local_z = -1;
	for (uint64_t z=0; z<=15; ++z)
for (uint64_t xi = 0; xi<map->mapWidth; xi+=256)
	for (uint64_t yi = 0; yi<map->mapHeight; yi+=256)
            for (uint64_t x = xi; x<xi+256; x++)  
                for (uint64_t y = yi; y<yi+256; y++){
			//MapIterator map_iterator = map.begin();
			//while(map_iterator != map.end()) {
				// Update progressbar
				//++tiles_saved;
				//if(showdialog && tiles_saved % 8192 == 0) {
					//gui.SetLoadDone(int(tiles_saved / double(map.getTileCount()) * 100.0));
				//}

				// Get tile
				Tile* save_tile = map->getTile(x,y,z); //Tile* save_tile = *map_iterator;				
	        	if (!save_tile)
		      	continue;
				const Position& pos = save_tile->getPosition();

				/*// Is it an empty tile that we can skip? (Leftovers...)
				if(save_tile->size() == 0) {
					++map_iterator;
					continue;
				}*/

				// Decide if new node should be created
				if(pos.x < local_x || pos.x >= local_x + 256 ||
				   pos.y < local_y || pos.y >= local_y + 256 ||
				   pos.z != local_z) {
					// End last node
					if(!first) {
					f.endNode();
					}
					first = false;

					// Start new node
					f.startNode(OTBM_TILE_AREA);
					f.addU16(local_x = pos.x & 0xFF00);
					f.addU16(local_y = pos.y & 0xFF00);
					f.addU8( local_z = pos.z);
				}
				//HouseTile* houseTile = dynamic_cast<HouseTile*>(save_tile);
				f.startNode(/*houseTile? OTBM_HOUSETILE : */OTBM_TILE);
				
				f.addU8(pos.x & 0xFF);
				f.addU8(pos.y & 0xFF);

				/*if(houseTile) {
					f.addU32(houseTile->getHouse()->getHouseId());
				}*/
				/*if(save_tile->getMapFlags()) {
					f.addByte(OTBM_ATTR_TILE_FLAGS);
					f.addU32(save_tile->getMapFlags());
				}*/

				if(save_tile->ground) {
					Item* ground = save_tile->ground;
					/*if(ground->hasBorderEquivalent()) {
						bool found = false;
						for(ItemVector::iterator it = save_tile->items.begin(); it != save_tile->items.end(); ++it) {
							if((*it)->getGroundEquivalent() == ground->getID()) {
								// Do nothing
								// Found equivalent
								found = true;
								break;
							}
						}
						if(found == false) {
							ground->serializeItemNode_OTBM(*this, f);
						}
					} else*/ if(ground->isComplex()) {
						ground->serializeItemNode_OTBM(f);
					} else {
						f.addByte(OTBM_ATTR_ITEM);
						ground->serializeItemCompact_OTBM(f);
					}
				}

				for(ItemVector::reverse_iterator it = save_tile->downItems.rbegin(); it != save_tile->downItems.rend(); ++it) {
					//if(!(*it)->isMetaItem()) {
						(*it)->serializeItemNode_OTBM(f);
					//}
				}
				for(ItemVector::iterator it = save_tile->topItems.begin(); it != save_tile->topItems.end(); ++it) {
					//if(!(*it)->isMetaItem()) {
						(*it)->serializeItemNode_OTBM(f);
					//}
				}
				f.endNode();

				//++map_iterator;
			}
			// Only close the last node if one has actually been created
			if(!first) {
				f.endNode();
			}

			f.startNode(OTBM_TOWNS); {
				//for(TownMap::const_iterator it = townMap.begin(); it != townMap.end(); ++it) {
                for(TownMap::const_iterator it = Towns::getInstance().getFirstTown(); it != Towns::getInstance().getLastTown(); ++it){
					Town* town = it->second;
					f.startNode(OTBM_TOWN);

					f.addU32(town->getTownID());
					f.addString(town->getName());
					f.addU16(town->getTemplePosition().x);
					f.addU16(town->getTemplePosition().y);
					f.addU8 (town->getTemplePosition().z);
					f.endNode();
				}
			} f.endNode();
		} f.endNode();
	//std::cout << tiles_saved << std::endl;
	} f.endNode();

	/*if(showdialog) gui.SetLoadDone(100, wxT("Saving spawns..."));
	saveSpawns(map, identifier);
	if(gui.GetCurrentVersion() > CLIENT_VERSION_760) {
		if(showdialog) gui.SetLoadDone(100, wxT("Saving houses..."));
		saveHouses(map, identifier);
	}*/
	return true;
}

item.h, public of class Item:
Code:
		//map-saving
		virtual bool serializeItemNode_OTBM(FileLoader& f) const;
		// Will write this item to the stream supplied in the argument
		virtual void serializeItemCompact_OTBM(FileLoader& f) const;
		virtual void serializeItemAttributes_OTBM(FileLoader& f) const;

item.h, public of class ItemAttributes:
Code:
virtual bool isComplex() const {return (15 & m_attributes) != 0;}

item.cpp:
Code:
bool Item::serializeItemNode_OTBM(FileLoader& f) const {
	f.startNode(OTBM_ITEM);
	f.addU16(id);

	//if(maphandle.version == 0) {
		/*const ItemType& iType = items[id];

		if(iType.stackable || iType.isSplash() || iType.isFluidContainer()){
			f.addU8(getSubType());
		}*/
	//}

	serializeItemAttributes_OTBM(f);
	f.endNode();

	return true;
}

void Item::serializeItemAttributes_OTBM(FileLoader& stream) const {
	//if(maphandle.version > 0) {
		const ItemType& iType = items[id];

		if(iType.stackable || iType.isSplash() || iType.isFluidContainer()){
			//stream.addU8(OTBM_ATTR_COUNT);
			stream.addU8(getItemCountOrSubtype());
		}
	//}*/

/*	if(items.dwMinorVersion >= CLIENT_VERSION_820 && isCharged()) {
		stream.addU8(OTBM_ATTR_CHARGES);
		stream.addU16(getSubtype());
	}*/

	if(getActionId()) {
		stream.addU8(OTBM_ATTR_ACTION_ID);
		stream.addU16(getActionId());
	}

	if(getUniqueId()) {
		stream.addU8(OTBM_ATTR_UNIQUE_ID);
		stream.addU16(getUniqueId());
	}

	if(getText().length() > 0) {
		stream.addU8(OTBM_ATTR_TEXT);
		stream.addString(getText());
	}

	if(getSpecialDescription().length() > 0) {
		stream.addU8(OTBM_ATTR_DESC);
		stream.addString(getSpecialDescription());
	}
}

void Item::serializeItemCompact_OTBM(FileLoader& stream) const {
	stream.addU16(id);

	/* This is impossible
	const ItemType& iType = item_db[id];

	if(iType.stackable || iType.isSplash() || iType.isFluidContainer()){
		stream.addU8(getSubtype());
	}
	*/
}

fileloader.cpp:
change the addU8 and the addU16 functions to this(or the map will be corrupted!!):

Code:
bool FileLoader::addU8(uint8_t u8) {
	writeData(&u8, sizeof(u8), true);  //unescape=true, or else some FEsomething itemid might be recognized as the start of a node
	return m_lastError == ERROR_NONE;
}

bool FileLoader::addU16(uint16_t u16) {
	writeData(reinterpret_cast<uint8_t*>(&u16), sizeof(u16), true);
	return m_lastError == ERROR_NONE;
}

How to use it? Just put saveMap() in a script, but beware it will lag a little.
You can easily create an NPC that saves the map every x hours, and if you restart the server for some reason just kick everyone and use a talkaction that saves.
 
PHP:
210 C:\Users\Oskar\Desktop\0.3.6pl1.r83\item.h `m_attributes' was not declared in this scope
PHP:
virtual bool isComplex() const {return (15 & m_attributes) != 0;}
 
PHP:
210 C:\Users\Oskar\Desktop\0.3.6pl1.r83\item.h `m_attributes' was not declared in this scope
PHP:
virtual bool isComplex() const {return (15 & m_attributes) != 0;}

weird..
can you pass me your item.h?
also, ctrl+f m_attributes, see where it is declared
 
#2up
I haven't declared this attribute.
My item.h
PHP:
////////////////////////////////////////////////////////////////////////
// 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/>.
////////////////////////////////////////////////////////////////////////

#ifndef __ITEM__
#define __ITEM__
#include "otsystem.h"

#include <libxml/xmlmemory.h>
#include <libxml/parser.h>

#include "thing.h"
#include "itemattributes.h"

#include "items.h"
#include "raids.h"

class Creature;
class Player;

class Container;
class Depot;

class TrashHolder;
class Mailbox;

class Teleport;
class MagicField;

class Door;
class BedItem;

enum ITEMPROPERTY
{
	BLOCKSOLID = 0,
	HASHEIGHT,
	BLOCKPROJECTILE,
	BLOCKPATH,
	ISVERTICAL,
	ISHORIZONTAL,
	MOVEABLE,
	IMMOVABLEBLOCKSOLID,
	IMMOVABLEBLOCKPATH,
	IMMOVABLENOFIELDBLOCKPATH,
	NOFIELDBLOCKPATH,
	SUPPORTHANGABLE
};

enum TradeEvents_t
{
	ON_TRADE_TRANSFER,
	ON_TRADE_CANCEL,
};

enum ItemDecayState_t
{
	DECAYING_FALSE = 0,
	DECAYING_TRUE,
	DECAYING_PENDING
};

enum AttrTypes_t
{
	ATTR_END = 0,
	//ATTR_DESCRIPTION = 1,
	//ATTR_EXT_FILE = 2,
	ATTR_TILE_FLAGS = 3,
	ATTR_ACTION_ID = 4,
	ATTR_UNIQUE_ID = 5,
	ATTR_TEXT = 6,
	ATTR_DESC = 7,
	ATTR_TELE_DEST = 8,
	ATTR_ITEM = 9,
	ATTR_DEPOT_ID = 10,
	//ATTR_EXT_SPAWN_FILE = 11,
	ATTR_RUNE_CHARGES = 12,
	//ATTR_EXT_HOUSE_FILE = 13,
	ATTR_HOUSEDOORID = 14,
	ATTR_COUNT = 15,
	ATTR_DURATION = 16,
	ATTR_DECAYING_STATE = 17,
	ATTR_WRITTENDATE = 18,
	ATTR_WRITTENBY = 19,
	ATTR_SLEEPERGUID = 20,
	ATTR_SLEEPSTART = 21,
	ATTR_CHARGES = 22,
	ATTR_CONTAINER_ITEMS = 23,
	ATTR_NAME = 30,
	ATTR_PLURALNAME = 31,
	ATTR_ATTACK = 33,
	ATTR_EXTRAATTACK = 34,
	ATTR_DEFENSE = 35,
	ATTR_EXTRADEFENSE = 36,
	ATTR_ARMOR = 37,
	ATTR_ATTACKSPEED = 38,
	ATTR_HITCHANCE = 39,
	ATTR_SHOOTRANGE = 40,
	ATTR_ARTICLE = 41,
	ATTR_SCRIPTPROTECTED = 42,
	ATTR_CRITICALHITCHANCE = 43,
	ATTR_MAGATTACK = 44,
	ATTR_LUCK = 45,
	ATTR_ANGNAME = 46,
	ATTR_ATTRIBUTE_MAP = 128
};

enum Attr_ReadValue
{
	ATTR_READ_CONTINUE,
	ATTR_READ_ERROR,
	ATTR_READ_END
};

// from iomap.h
#pragma pack(1)
struct TeleportDest
{
	uint16_t _x, _y;
	uint8_t _z;
};
#pragma pack()

typedef std::list<Item*> ItemList;

class Item : virtual public Thing, public ItemAttributes
{
	public:
		static Items items;

		//Factory member to create item of right type based on type
		static Item* CreateItem(const uint16_t type, uint16_t amount = 1);
		static Item* CreateItem(PropStream& propStream);

		static bool loadItem(xmlNodePtr node, Container* parent);
		static bool loadContainer(xmlNodePtr node, Container* parent);

		// Constructor for items
		Item(const uint16_t type, uint16_t amount = 0);
		Item(const Item &i): Thing(), ItemAttributes(i), id(i.id), count(i.count) {}
		virtual ~Item() {}

		virtual Item* clone() const;
		virtual void copyAttributes(Item* item);

		virtual Item* getItem() {return this;}
		virtual const Item* getItem() const {return this;}

		virtual Container* getContainer() {return NULL;}
		virtual const Container* getContainer() const {return NULL;}

		virtual Teleport* getTeleport() {return NULL;}
		virtual const Teleport* getTeleport() const {return NULL;}

		virtual TrashHolder* getTrashHolder() {return NULL;}
		virtual const TrashHolder* getTrashHolder() const {return NULL;}

		virtual Mailbox* getMailbox() {return NULL;}
		virtual const Mailbox* getMailbox() const {return NULL;}

		virtual Door* getDoor() {return NULL;}
		virtual const Door* getDoor() const {return NULL;}

		virtual MagicField* getMagicField() {return NULL;}
		virtual const MagicField* getMagicField() const {return NULL;}

		virtual BedItem* getBed() {return NULL;}
		virtual const BedItem* getBed() const {return NULL;}

		uint16_t getID() const {return id;}
		void setID(uint16_t newid);
		uint16_t getClientID() const {return items[id].clientId;}
		
		static std::string getDescription(const ItemType& it, int32_t lookDistance, const Item* item = NULL, int32_t subType = -1, bool polis = false);
        static std::string getNameDescription(const ItemType& it, const Item* item = NULL, int32_t subType = -1, bool polis = false);
        static std::string getWeightDescription(double weight, bool stackable, const Item* item = NULL, bool polis = false, uint32_t count = 1);

        virtual std::string getDescription(int32_t lookDistance, bool polis) const {return getDescription(items[id], lookDistance, this, -1, polis);}
        std::string getNameDescription() const {return getNameDescription(items[id], this);}
        std::string getWeightDescription(bool polis) const {return getWeightDescription(getWeight(), items[id].stackable, this, polis, count);}

		Player* getHoldingPlayer();
		const Player* getHoldingPlayer() const;

		//serialization
		virtual Attr_ReadValue readAttr(AttrTypes_t attr, PropStream& propStream);
		virtual bool unserializeAttr(PropStream& propStream);
		virtual bool serializeAttr(PropWriteStream& propWriteStream) const;
		virtual bool unserializeItemNode(FileLoader& f, NODE node, PropStream& propStream) {return unserializeAttr(propStream);}

		// Item attributes
		void setDuration(int32_t time) {setAttribute("duration", time);}
		void decreaseDuration(int32_t time);
		int32_t getDuration() const;

		void setSpecialDescription(const std::string& description) {setAttribute("description", description);}
		void resetSpecialDescription() {eraseAttribute("description");}
		std::string getSpecialDescription() const;

		void setText(const std::string& text) {setAttribute("text", text);}
		void resetText() {eraseAttribute("text");}
		std::string getText() const;

		void setDate(time_t date) {setAttribute("date", (int32_t)date);}
		void resetDate() {eraseAttribute("date");}
		time_t getDate() const;

		void setWriter(std::string writer) {setAttribute("writer", writer);}
		void resetWriter() {eraseAttribute("writer");}
		std::string getWriter() const;

		void setActionId(int32_t aid);
		void resetActionId();
		int32_t getActionId() const;

		void setUniqueId(int32_t uid);
		int32_t getUniqueId() const;

		void setCharges(uint16_t charges) {setAttribute("charges", charges);}
		uint16_t getCharges() const;

		void setFluidType(uint16_t fluidType) {setAttribute("fluidtype", fluidType);}
		uint16_t getFluidType() const;

		void setOwner(uint32_t owner) {setAttribute("owner", (int32_t)owner);}
		uint32_t getOwner() const;

		void setCorpseOwner(uint32_t corpseOwner) {setAttribute("corpseowner", (int32_t)corpseOwner);}
		uint32_t getCorpseOwner();

		void setDecaying(ItemDecayState_t state) {setAttribute("decaying", (int32_t)state);}
		ItemDecayState_t getDecaying() const;

		std::string getName() const;
		std::string getAngName() const;
		std::string getPluralName() const;
		std::string getArticle() const;
		bool isScriptProtected() const;

		int32_t getAttack() const;
		int32_t getMagAttack() const;
		int32_t getLuck() const;
		int32_t getCriticalHitChance() const;
		int32_t getExtraAttack() const;
		int32_t getDefense() const;
		int32_t getExtraDefense() const;

		int32_t getArmor() const;
		int32_t getAttackSpeed() const;
		int32_t getHitChance() const;
		int32_t getShootRange() const;

		Ammo_t getAmmoType() const {return items[id].ammoType;}
		WeaponType_t getWeaponType() const {return items[id].weaponType;}
		WeaponGroup_t getWeaponGroup() const {return items[id].weaponGroup;}
		int32_t getSlotPosition() const {return items[id].slotPosition;}
		int32_t getWieldPosition() const {return items[id].wieldPosition;}

		virtual double getWeight() const;
		void getLight(LightInfo& lightInfo);

		int32_t getMaxWriteLength() const {return items[id].maxTextLen;}
		int32_t getWorth() const {return getItemCount() * items[id].worth;}
		virtual int32_t getThrowRange() const {return (isPickupable() ? 15 : 2);}

		bool floorChange(FloorChange_t change = CHANGE_NONE) const;
		bool forceSerialize() const {return items[id].forceSerialize || canWriteText() || isContainer() || isBed() || isDoor();}

		bool hasProperty(enum ITEMPROPERTY prop) const;
		bool hasSubType() const {return items[id].hasSubType();}
		bool hasCharges() const {return items[id].charges;}

		bool canDecay();
		virtual bool canRemove() const {return true;}
		virtual bool canTransform() const {return true;}
		bool canWriteText() const {return items[id].canWriteText;}

		virtual bool isPushable() const {return !isNotMoveable();}
		bool isGroundTile() const {return items[id].isGroundTile();}
		bool isContainer() const {return items[id].isContainer();}
		bool isSplash() const {return items[id].isSplash();}
		bool isFluidContainer() const {return (items[id].isFluidContainer());}
		bool isDoor() const {return items[id].isDoor();}
		bool isMagicField() const {return items[id].isMagicField();}
		bool isTeleport() const {return items[id].isTeleport();}
		bool isKey() const {return items[id].isKey();}
		bool isDepot() const {return items[id].isDepot();}
		bool isMailbox() const {return items[id].isMailbox();}
		bool isTrashHolder() const {return items[id].isTrashHolder();}
		bool isBed() const {return items[id].isBed();}
		bool isRune() const {return items[id].isRune();}
		bool isBlocking(const Creature* creature) const {return items[id].blockSolid;}
		bool isStackable() const {return items[id].stackable;}
		bool isAlwaysOnTop() const {return items[id].alwaysOnTop;}
		bool isNotMoveable() const {return !items[id].moveable;}
		bool isMoveable() const {return items[id].moveable;}
		bool isPickupable() const {return items[id].pickupable;}
		bool isUseable() const {return items[id].useable;}
		bool isHangable() const {return items[id].isHangable;}
		bool isRoteable() const {const ItemType& it = items[id]; return it.rotable && it.rotateTo;}
		bool isWeapon() const {return (items[id].weaponType != WEAPON_NONE);}
		bool isReadable() const {return items[id].canReadText;}

		bool isLoadedFromMap() const {return loadedFromMap;}
		void setLoadedFromMap(bool value) {loadedFromMap = value;}

		uint16_t getItemCount() const {return count;}
		void setItemCount(uint16_t n) {count = n;}

		uint16_t getSubType() const;
		void setSubType(uint16_t n);

		uint32_t getDefaultDuration() const {return items[id].decayTime * 1000;}
		void setDefaultDuration()
		{
			uint32_t duration = getDefaultDuration();
			if(duration)
				setDuration(duration);
		}

		Raid* getRaid() {return raid;}
		void setRaid(Raid* _raid) {raid = _raid;}

		virtual void onRemoved();
		virtual bool onTradeEvent(TradeEvents_t event, Player* owner, Player* seller) {return true;}

		void setDefaultSubtype();
		virtual void __startDecaying();
		static uint32_t countByType(const Item* item, int32_t checkType, bool multiCount);

	protected:
		uint16_t id;
		uint8_t count;

		Raid* raid;
		bool loadedFromMap;
};

inline std::string Item::getName() const
{
	const std::string* v = getStringAttribute("name");
	if(v)
		return *v;

	return items[id].name;
}

inline std::string Item::getAngName() const
{
	const std::string* v = getStringAttribute("angname");
	if(v)
		return *v;

	return items[id].angName;
}

inline std::string Item::getPluralName() const
{
	const std::string* v = getStringAttribute("pluralname");
	if(v)
		return *v;

	return items[id].pluralName;
}

inline std::string Item::getArticle() const
{
	const std::string* v = getStringAttribute("article");
	if(v)
		return *v;

	return items[id].article;
}

inline bool Item::isScriptProtected() const
{
	const bool* v = getBooleanAttribute("scriptprotected");
	if(v)
		return *v;

	return false;
}

inline int32_t Item::getCriticalHitChance() const
{
	const int32_t* v = getIntegerAttribute("criticalhitchance");
	if(v)
		return *v;
 
	return items[id].criticalHitChance;
}

inline int32_t Item::getMagAttack() const
{
	const int32_t* v = getIntegerAttribute("magattack");
	if(v)
		return *v;
 
	return items[id].magAttack;
}

inline int32_t Item::getLuck() const
{
	const int32_t* v = getIntegerAttribute("luck");
	if(v)
		return *v;
 
	return items[id].luck;
}

inline int32_t Item::getAttack() const
{
	const int32_t* v = getIntegerAttribute("attack");
	if(v)
		return *v;

	return items[id].attack;
}

inline int32_t Item::getExtraAttack() const
{
	const int32_t* v = getIntegerAttribute("extraattack");
	if(v)
		return *v;

	return items[id].extraAttack;
}

inline int32_t Item::getDefense() const
{
	const int32_t* v = getIntegerAttribute("defense");
	if(v)
		return *v;

	return items[id].defense;
}

inline int32_t Item::getExtraDefense() const
{
	const int32_t* v = getIntegerAttribute("extradefense");
	if(v)
		return *v;

	return items[id].extraDefense;
}

inline int32_t Item::getArmor() const
{
	const int32_t* v = getIntegerAttribute("armor");
	if(v)
		return *v;

	return items[id].armor;
}

inline int32_t Item::getAttackSpeed() const
{
	const int32_t* v = getIntegerAttribute("attackspeed");
	if(v)
		return *v;

	return items[id].attackSpeed;
}

inline int32_t Item::getHitChance() const
{
	const int32_t* v = getIntegerAttribute("hitchance");
	if(v)
		return *v;

	return items[id].hitChance;
}

inline int32_t Item::getShootRange() const
{
	const int32_t* v = getIntegerAttribute("shootrange");
	if(v)
		return *v;

	return items[id].shootRange;
}

inline void Item::decreaseDuration(int32_t time)
{
	const int32_t* v = getIntegerAttribute("duration");
	if(v)
		setAttribute("duration", *v - time);
}

inline int32_t Item::getDuration() const
{
	const int32_t* v = getIntegerAttribute("duration");
	if(v)
		return *v;

	return 0;
}

inline std::string Item::getSpecialDescription() const
{
	const std::string* v = getStringAttribute("description");
	if(v)
		return *v;

	return "";
}

inline std::string Item::getText() const
{
	const std::string* v = getStringAttribute("text");
	if(v)
		return *v;

	return "";
}

inline time_t Item::getDate() const
{
	const int32_t* v = getIntegerAttribute("date");
	if(v)
		return (time_t)*v;

	return 0;
}

inline std::string Item::getWriter() const
{
	const std::string* v = getStringAttribute("writer");
	if(v)
		return *v;

	return "";
}

inline int32_t Item::getActionId() const
{
	const int32_t* v = getIntegerAttribute("aid");
	if(v)
		return *v;

	return 0;
}

inline int32_t Item::getUniqueId() const
{
	const int32_t* v = getIntegerAttribute("uid");
	if(v)
		return *v;

	return 0;
}

inline uint16_t Item::getCharges() const
{
	const int32_t* v = getIntegerAttribute("charges");
	if(v && *v >= 0)
		return (uint16_t)*v;

	return 0;
}

inline uint16_t Item::getFluidType() const
{
	const int32_t* v = getIntegerAttribute("fluidtype");
	if(v && *v >= 0)
		return (uint16_t)*v;

	return 0;
}

inline uint32_t Item::getOwner() const
{
	const int32_t* v = getIntegerAttribute("owner");
	if(v)
		return (uint32_t)*v;

	return 0;
}

inline uint32_t Item::getCorpseOwner()
{
	const int32_t* v = getIntegerAttribute("corpseowner");
	if(v)
		return (uint32_t)*v;

	return 0;
}

inline ItemDecayState_t Item::getDecaying() const
{
	const int32_t* v = getIntegerAttribute("decaying");
	if(v)
		return (ItemDecayState_t)*v;

	return DECAYING_FALSE;
}

inline uint32_t Item::countByType(const Item* item, int32_t checkType, bool multiCount)
{
	if(checkType != -1 && checkType != (int32_t)item->getSubType())
		return 0;

	if(multiCount)
		return item->getItemCount();

	if(item->isRune())
		return item->getCharges();

	return item->getItemCount();
}
#endif
 
@oskar

I think in your case it is declared in itemattributes.h


itemattributes.h, public of class ItemAttributes:
Code:
virtual bool isComplex() const {return (15 & m_attributes) != 0;}
 
Going to test this with 0.4 and will post back later with results..
 
i guess i'm the only one who tested it, but it worked fine with me, didn't find any bugs...

if you wanna test it too, it would be great
 
am Sorry,How Could i Edit This Files?
With Notepad +?
Or do i need a Certain item.?
 
Can someone update this to work with TFS 0.3.7? I'd really appreciate it!
 
Back
Top