• 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!

MoveEvent Infinity training room [0.3.6 & 0.4~]

Erikas Kontenis

Board Moderator
Staff member
Board Moderator
Joined
Jul 3, 2009
Messages
1,864
Reaction score
566
Location
Lithuania
What is it?
It's a movement script that creates a own training room for player, in random void position you will select from your map cordinates. When player don't want to train anymore, he go to teleport in training room and he will be teleported, also training room will dissapear, because we saving infinity space ofcourse :D.

Why use it?
Well, I self never liked to create training rooms, I even dislike to open map editor it is pain to my heart and head. But that's not a reason you should to use script. The main reason is, you not must to spend your time in creating huge and large training rooms for players, everything what you will have to do in map editor is create teleport where you want and set action id: 8770 on it.

Can it lag or crash server?
I don't think so, it's very basic script it maybe can looks huge but it isin't. You even can set cords 20kx20k.

for 0.3.6 it will requires some source changes, because you not allowed to createItem in Void it wont take too much time, here it is:

luascript.cpp

find this function line:

Code:
int32_t LuaScriptInterface::luaDoCreateItem(lua_State* L)

and replace it all to this:

Code:
int32_t LuaScriptInterface::luaDoCreateItem(lua_State* L)
{
	//doCreateItem(itemid[, type/count], pos)
	//Returns uid of the created item, only works on tiles.
	PositionEx pos;
	popPosition(L, pos);

	uint32_t count = 1;
	if(lua_gettop(L) > 1)
		count = popNumber(L);

	uint32_t itemId = popNumber(L);
	ScriptEnviroment* env = getEnv();

	Tile* tile = g_game.getTile(pos);
	const ItemType& it = Item::items[itemId];
	if((!tile))
	{
		if(it.group == ITEM_GROUP_GROUND)
		{
			Item* item = Item::CreateItem(itemId);
			tile = IOMap::createTile(item, NULL, pos.x, pos.y, pos.z);

			g_game.setTile(tile);
			tile->onUpdateTile();
			
			lua_pushnumber(L, env->addThing(item));
			return 1;
		}
		else
		{
			errorEx(getError(LUA_ERROR_TILE_NOT_FOUND));
			lua_pushboolean(L, false);
			return 1;
		}
	}

	int32_t itemCount = 1, subType = 1;
	if(it.hasSubType())
	{
		if(it.stackable)
			itemCount = (int32_t)std::ceil((float)count / 100);

		subType = count;
	}
	else
		itemCount = std::max((uint32_t)1, count);

	while(itemCount > 0)
	{
		int32_t stackCount = std::min(100, subType);
		Item* newItem = Item::CreateItem(itemId, stackCount);
		if(!newItem)
		{
			errorEx(getError(LUA_ERROR_ITEM_NOT_FOUND));
			lua_pushboolean(L, false);
			return 1;
		}

		if(it.stackable)
			subType -= stackCount;

		ReturnValue ret = g_game.internalAddItem(NULL, tile, newItem, INDEX_WHEREEVER, FLAG_NOLIMIT);
		if(ret != RET_NOERROR)
		{
			delete newItem;
			lua_pushboolean(L, false);
			return 1;
		}
		--itemCount;
		if(itemCount)
			continue;

		if(newItem->getParent())
			lua_pushnumber(L, env->addThing(newItem));
		else //stackable item stacked with existing object, newItem will be released
			lua_pushnil(L);

		return 1;
	}

	lua_pushnil(L);
	return 1;
}

iomap.h

find this line:

Code:
 static Tile* createTile(Item*& ground, Item* item, uint16_t px, uint16_t py, uint16_t pz);

and you need it to move in public section result will look like this:

Code:
class IOMap
{
	public:
		IOMap() {}
		virtual ~IOMap() {}

		static Tile* createTile(Item*& ground, Item* item, uint16_t px, uint16_t py, uint16_t pz);
		bool loadMap(Map* map, const std::string& identifier);

		/* Load the spawns
		 * \param map pointer to the Map class
		 * \returns Returns true if the spawns were loaded successfully
		 */
		bool loadSpawns(Map* map);

		/* Load the houses (not house tile-data)
		 * \param map pointer to the Map class
		 * \returns Returns true if the houses were loaded successfully
		 */
		bool loadHouses(Map* map);

		const std::string& getLastErrorString() const {return errorString;}
		void setLastErrorString(const std::string& _errorString) {errorString = _errorString;}

	protected:
		std::string errorString;
};

tile.h

find this line:

Code:
void onUpdateTile();

and you need it to move in public section result will look like this:

Code:
class Tile : public Cylinder
{
	public:
		static Tile& nullTile;
		Tile(uint16_t x, uint16_t y, uint16_t z);
		virtual ~Tile();

		TileItemVector* getItemList();
		const TileItemVector* getItemList() const;
		TileItemVector* makeItemList();

		CreatureVector* getCreatures();
		const CreatureVector* getCreatures() const;
		CreatureVector* makeCreatures();

		HouseTile* getHouseTile();
		const HouseTile* getHouseTile() const;
		bool isHouseTile() const {return hasFlag(TILESTATE_HOUSE);}

		MagicField* getFieldItem() const;
		Teleport* getTeleportItem() const;
		TrashHolder* getTrashHolder() const;
		Mailbox* getMailbox() const;
		BedItem* getBedItem() const;

		Creature* getTopCreature();
		Item* getTopTopItem();
		Item* getTopDownItem();
		bool isMoveableBlocking() const;
		Thing* getTopVisibleThing(const Creature* creature);
		Creature* getTopVisibleCreature(const Creature* creature);
		const Creature* getTopVisibleCreature(const Creature* creature) const;
		Item* getItemByTopOrder(uint32_t topOrder);

		uint32_t getThingCount() const {return thingCount;}
		uint32_t getCreatureCount() const;
		uint32_t getItemCount() const;
		uint32_t getTopItemCount() const;
		uint32_t getDownItemCount() const;

		bool hasProperty(enum ITEMPROPERTY prop) const;
		bool hasProperty(Item* exclude, enum ITEMPROPERTY prop) const;

		bool hasFlag(tileflags_t flag) const {return ((m_flags & (uint32_t)flag) == (uint32_t)flag);}
		void setFlag(tileflags_t flag) {m_flags |= (uint32_t)flag;}
		void resetFlag(tileflags_t flag) {m_flags &= ~(uint32_t)flag;}

		bool positionChange() const {return hasFlag(TILESTATE_TELEPORT);}
		bool floorChange(FloorChange_t change = CHANGE_NONE) const
		{
			switch(change)
			{
				case CHANGE_DOWN:
					return hasFlag(TILESTATE_FLOORCHANGE_DOWN);
				case CHANGE_NORTH:
					return hasFlag(TILESTATE_FLOORCHANGE_NORTH);
				case CHANGE_SOUTH:
					return hasFlag(TILESTATE_FLOORCHANGE_SOUTH);
				case CHANGE_EAST:
					return hasFlag(TILESTATE_FLOORCHANGE_EAST);
				case CHANGE_WEST:
					return hasFlag(TILESTATE_FLOORCHANGE_WEST);
				case CHANGE_NORTH_EX:
					return hasFlag(TILESTATE_FLOORCHANGE_NORTH_EX);
				case CHANGE_SOUTH_EX:
					return hasFlag(TILESTATE_FLOORCHANGE_SOUTH_EX);
				case CHANGE_EAST_EX:
					return hasFlag(TILESTATE_FLOORCHANGE_EAST_EX);
				case CHANGE_WEST_EX:
					return hasFlag(TILESTATE_FLOORCHANGE_WEST_EX);
				case CHANGE_NONE:
					return hasFlag(TILESTATE_FLOORCHANGE);
				default:
					break;
			}

			return false;
		}

		ZoneType_t getZone() const
		{
			if(hasFlag(TILESTATE_PROTECTIONZONE))
				return ZONE_PROTECTION;

			if(hasFlag(TILESTATE_NOPVPZONE))
				return ZONE_NOPVP;

			if(hasFlag(TILESTATE_PVPZONE))
				return ZONE_PVP;

			return ZONE_NORMAL;
		}

		bool isSwimmingPool(bool checkPz = true) const;
		bool hasHeight(uint32_t n) const;

		void moveCreature(Creature* actor, Creature* creature, Cylinder* toCylinder, bool forceTeleport = false);
		int32_t getClientIndexOfThing(const Player* player, const Thing* thing) const;

		//cylinder implementations
		virtual Cylinder* getParent() {return NULL;}
		virtual const Cylinder* getParent() const {return NULL;}
		virtual bool isRemoved() const {return false;}
		virtual Position getPosition() const {return pos;}
		virtual Tile* getTile() {return this;}
		virtual const Tile* getTile() const {return this;}
		virtual Item* getItem() {return NULL;}
		virtual const Item* getItem() const {return NULL;}
		virtual Creature* getCreature() {return NULL;}
		virtual const Creature* getCreature() const {return NULL;}

		virtual ReturnValue __queryAdd(int32_t index, const Thing* thing, uint32_t count,
			uint32_t flags) const;
		virtual ReturnValue __queryMaxCount(int32_t index, const Thing* thing, uint32_t count,
			uint32_t& maxQueryCount, uint32_t flags) const;
		virtual ReturnValue __queryRemove(const Thing* thing, uint32_t count, uint32_t flags) const;
		virtual Cylinder* __queryDestination(int32_t& index, const Thing* thing, Item** destItem,
			uint32_t& flags);

		virtual void __addThing(Creature* actor, Thing* thing) {__addThing(actor, 0, thing);}
		virtual void __addThing(Creature* actor, int32_t index, Thing* thing);

		virtual void __updateThing(Thing* thing, uint16_t itemId, uint32_t count);
		virtual void __replaceThing(uint32_t index, Thing* thing);

		virtual void __removeThing(Thing* thing, uint32_t count);

		virtual int32_t __getIndexOfThing(const Thing* thing) const;
		virtual int32_t __getFirstIndex() const {return 0;}
		virtual int32_t __getLastIndex() const {return thingCount;}
		virtual uint32_t __getItemTypeCount(uint16_t itemId, int32_t subType = -1, bool itemCount = true) const;
		virtual Thing* __getThing(uint32_t index) const;

		virtual void postAddNotification(Creature* actor, Thing* thing, const Cylinder* oldParent,
			int32_t index, cylinderlink_t link = LINK_OWNER);
		virtual void postRemoveNotification(Creature* actor, Thing* thing, const Cylinder* newParent,
			int32_t index, bool isCompleteRemoval, cylinderlink_t link = LINK_OWNER);

		virtual void __internalAddThing(Thing* thing) {__internalAddThing(0, thing);}
		virtual void __internalAddThing(uint32_t index, Thing* thing);
		void onUpdateTile();

	private:
		void onAddTileItem(Item* item);
		void onUpdateTileItem(Item* oldItem, const ItemType& oldType, Item* newItem, const ItemType& newType);
		void onRemoveTileItem(const SpectatorVec& list, std::vector<uint32_t>& oldStackPosVector, Item* item);

		void updateTileFlags(Item* item, bool removed);

	protected:
		bool isDynamic() const {return (m_flags & TILESTATE_DYNAMIC_TILE);}

	public:
		QTreeLeafNode* qt_node;
		Item* ground;

	protected:
		Position pos;
		uint32_t m_flags, thingCount;
};

So thats all for 0.3.6 source edits, and 0.4 don't need it.

LUA PART FOR BOTH 0.3.6 and 0.4:

movements.xml

Code:
<movevent type="StepIn" actionid="8770" event="script" value="custom/training_tile_in.lua" />
<movevent type="StepIn" actionid="8771" event="script" value="custom/training_tile_out.lua" />

custom/training_tile_in.lua

Lua:
local config = {
	fromPosition = {x = 1008, y = 795, z = 12}, -- void area (black screen in map editor) south-west corner
        toPosition = {x = 1210, y = 853, z = 15}, -- void area (black screen in map editor) north-east corner
	-- A hint toPosition config cordinates numbers must be higher than fromPosition cordinates numbers
	
	teleport = 1387,
	fire = 1484,
	northWall = 1114,
	northWallSmall = 1113,
	westNorthWall = 1115,
	westWall = 1116,
	ground = 406
}

function onStepIn(cid, item, pos)
	local pos = {x = math.random(config.fromPosition.x, config.toPosition.x), y = math.random(config.fromPosition.y, config.toPosition.y), z = math.random(config.fromPosition.z, config.toPosition.z)}
	resultPos = pos
	if getTileItemById({x=resultPos.x, y=resultPos.y, z=resultPos.z}, config.ground).uid < 1 then
		if getTileItemById({x=resultPos.x+1, y=resultPos.y, z=resultPos.z}, config.ground).uid < 1 then
			if getTileItemById({x=resultPos.x+2, y=resultPos.y, z=resultPos.z}, config.ground).uid < 1 then
				if getTileItemById({x=resultPos.x+3, y=resultPos.y, z=resultPos.z}, config.ground).uid < 1 then
					if getTileItemById({x=resultPos.x+4, y=resultPos.y, z=resultPos.z}, config.ground).uid < 1 then

		if getTileItemById({x=resultPos.x, y=resultPos.y+1, z=resultPos.z}, config.ground).uid < 1 then
			if getTileItemById({x=resultPos.x, y=resultPos.y+2, z=resultPos.z}, config.ground).uid < 1 then
				if getTileItemById({x=resultPos.x, y=resultPos.y+3, z=resultPos.z}, config.ground).uid < 1 then
					if getTileItemById({x=resultPos.x, y=resultPos.y+4, z=resultPos.z}, config.ground).uid < 1 then

		if getTileItemById({x=resultPos.x+4, y=resultPos.y+1, z=resultPos.z}, config.ground).uid < 1 then
			if getTileItemById({x=resultPos.x+4, y=resultPos.y+2, z=resultPos.z}, config.ground).uid < 1 then
				if getTileItemById({x=resultPos.x+4, y=resultPos.y+3, z=resultPos.z}, config.ground).uid < 1 then
					if getTileItemById({x=resultPos.x+4, y=resultPos.y+4, z=resultPos.z}, config.ground).uid < 1 then
		
		if getTileItemById({x=resultPos.x+1, y=resultPos.y+4, z=resultPos.z}, config.ground).uid < 1 then
			if getTileItemById({x=resultPos.x+2, y=resultPos.y+4, z=resultPos.z}, config.ground).uid < 1 then
				if getTileItemById({x=resultPos.x+3, y=resultPos.y+4, z=resultPos.z}, config.ground).uid < 1 then
					
		if getTileItemById({x=resultPos.x+1, y=resultPos.y+3, z=resultPos.z}, config.ground).uid < 1 then
			if getTileItemById({x=resultPos.x+2, y=resultPos.y+3, z=resultPos.z}, config.ground).uid < 1 then
				if getTileItemById({x=resultPos.x+3, y=resultPos.y+3, z=resultPos.z}, config.ground).uid < 1 then
				
		if getTileItemById({x=resultPos.x+1, y=resultPos.y+2, z=resultPos.z}, config.ground).uid < 1 then
			if getTileItemById({x=resultPos.x+2, y=resultPos.y+2, z=resultPos.z}, config.ground).uid < 1 then
				if getTileItemById({x=resultPos.x+3, y=resultPos.y+2, z=resultPos.z}, config.ground).uid < 1 then
				
		if getTileItemById({x=resultPos.x+1, y=resultPos.y+1, z=resultPos.z}, config.ground).uid < 1 then
			if getTileItemById({x=resultPos.x+2, y=resultPos.y+1, z=resultPos.z}, config.ground).uid < 1 then
				if getTileItemById({x=resultPos.x+3, y=resultPos.y+1, z=resultPos.z}, config.ground).uid < 1 then
				
						doCreateItem(config.ground, 1, {x=resultPos.x, y=resultPos.y, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x+1, y=resultPos.y, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x+2, y=resultPos.y, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x+3, y=resultPos.y, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x+4, y=resultPos.y, z=resultPos.z})
						
						doCreateItem(config.northWallSmall, 1, {x=resultPos.x, y=resultPos.y, z=resultPos.z})
						doCreateItem(config.northWall, 1, {x=resultPos.x+1, y=resultPos.y, z=resultPos.z})
						doCreateItem(config.northWall, 1, {x=resultPos.x+2, y=resultPos.y, z=resultPos.z})
						doCreateItem(config.northWall, 1, {x=resultPos.x+3, y=resultPos.y, z=resultPos.z})
						doCreateItem(config.northWall, 1, {x=resultPos.x+4, y=resultPos.y, z=resultPos.z})
						
						doCreateItem(config.ground, 1, {x=resultPos.x, y=resultPos.y+1, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x, y=resultPos.y+2, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x, y=resultPos.y+3, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x, y=resultPos.y+4, z=resultPos.z})
						
						doCreateItem(config.westWall, 1, {x=resultPos.x, y=resultPos.y+1, z=resultPos.z})
						doCreateItem(config.westWall, 1, {x=resultPos.x, y=resultPos.y+2, z=resultPos.z})
						doCreateItem(config.westWall, 1, {x=resultPos.x, y=resultPos.y+3, z=resultPos.z})
						doCreateItem(config.westWall, 1, {x=resultPos.x, y=resultPos.y+4, z=resultPos.z})
						
						doCreateItem(config.ground, 1, {x=resultPos.x+4, y=resultPos.y+1, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x+4, y=resultPos.y+2, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x+4, y=resultPos.y+3, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x+4, y=resultPos.y+4, z=resultPos.z})
						
						doCreateItem(config.westWall, 1, {x=resultPos.x+4, y=resultPos.y+1, z=resultPos.z})
						doCreateItem(config.westWall, 1, {x=resultPos.x+4, y=resultPos.y+2, z=resultPos.z})
						doCreateItem(config.westWall, 1, {x=resultPos.x+4, y=resultPos.y+3, z=resultPos.z})
						doCreateItem(config.westNorthWall, 1, {x=resultPos.x+4, y=resultPos.y+4, z=resultPos.z})
						
						doCreateItem(config.ground, 1, {x=resultPos.x+1, y=resultPos.y+4, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x+2, y=resultPos.y+4, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x+3, y=resultPos.y+4, z=resultPos.z})
						
						doCreateItem(config.northWall, 1, {x=resultPos.x+1, y=resultPos.y+4, z=resultPos.z})
						doCreateItem(config.northWall, 1, {x=resultPos.x+2, y=resultPos.y+4, z=resultPos.z})
						doCreateItem(config.northWall, 1, {x=resultPos.x+3, y=resultPos.y+4, z=resultPos.z})
						
						doCreateItem(config.ground, 1, {x=resultPos.x+1, y=resultPos.y+3, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x+2, y=resultPos.y+3, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x+3, y=resultPos.y+3, z=resultPos.z})
						
						doCreateItem(config.ground, 1, {x=resultPos.x+1, y=resultPos.y+2, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x+2, y=resultPos.y+2, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x+3, y=resultPos.y+2, z=resultPos.z})
						
						doCreateItem(config.ground, 1, {x=resultPos.x+1, y=resultPos.y+1, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x+2, y=resultPos.y+1, z=resultPos.z})
						doCreateItem(config.ground, 1, {x=resultPos.x+3, y=resultPos.y+1, z=resultPos.z})
						
						doCreateMonster("Training Monk", {x=resultPos.x+1, y=resultPos.y+1, z=resultPos.z})
						local tele = doCreateItem(config.teleport, 1, {x=resultPos.x+2, y=resultPos.y+1, z=resultPos.z})
						doItemSetAttribute(tele, "aid", 8771)
						local roomGround = doCreateItem(config.ground, 1, {x=resultPos.x+2, y=resultPos.y+2, z=resultPos.z})
						doItemSetAttribute(roomGround, "aid", 8772)
						local roomGround2 = doCreateItem(config.ground, 1, {x=resultPos.x+2, y=resultPos.y+3, z=resultPos.z})
						doItemSetAttribute(roomGround2, "aid", 8772)
						doTeleportThing(cid, {x=resultPos.x+2, y=resultPos.y+2, z=resultPos.z})
						doSendMagicEffect({x=resultPos.x+2, y=resultPos.y+2, z=resultPos.z}, CONST_ME_TELEPORT)
						doCreateMonster("Training Monk", {x=resultPos.x+3, y=resultPos.y+1, z=resultPos.z})
						
						doCreateItem(config.fire, 1, {x=resultPos.x+1, y=resultPos.y+2, z=resultPos.z})
						doCreateItem(config.fire, 1, {x=resultPos.x+1, y=resultPos.y+3, z=resultPos.z})
						doCreateItem(config.fire, 1, {x=resultPos.x+3, y=resultPos.y+2, z=resultPos.z})
						doCreateItem(config.fire, 1, {x=resultPos.x+3, y=resultPos.y+3, z=resultPos.z})
					end
				end
			end
		end
	end
					end
				end
			end
		end
		
					end
				end
			end
		end
		
					
				end
			end
		end
		
				end
			end
		end
		
				end
			end
		end
		
				end
			end
		end

    return true
end

custom/training_tile_out.lua
Lua:
function onStepIn(cid, item, pos)
local playerpos = getCreaturePosition(cid)
	for x = playerpos.x-2, playerpos.x+2 do
		for y = playerpos.y-1, playerpos.y+3 do
			for z = playerpos.z, playerpos.z do
				local pos = {x=x, y=y, z=z, stackpos = 253}
				local thing = getThingfromPos(pos)
				if thing.itemid > 0 then
					doRemoveCreature(thing.uid)
				end
				local pos = {x=x, y=y, z=z, stackpos = 1}
				local thing = getThingfromPos(pos)
				if thing.itemid > 0 then
					doRemoveItem(thing.uid)
				end
				local pos = {x=x, y=y, z=z}
				local thing = getThingfromPos(pos)
				if thing.itemid > 0 then
					doRemoveItem(thing.uid)
				end
			end
		end
	end
    return true
end

Important to know: This script/code was not supposed to be for public, I don't care about tabbing or shortings it is supposed to be for my project but because lack of time I had to leave it. And I felt friendly ofcourse to release it =^_^=

However if something not working, let me know ofcourse I will fix it.


trainersm.png
 
Last edited:
This is AWESOME Idea!!! But, you should show a ss of how the area looks when you are there.... My question to make sure I understand right, anybody can go thru, and more and more players can keep going thru and get training, but not see each other, it would be in their own space of nothingness?
 
This is AWESOME Idea!!! But, you should show a ss of how the area looks when you are there.... My question to make sure I understand right, anybody can go thru, and more and more players can keep going thru and get training, but not see each other, it would be in their own space of nothingness?

Yes, you are right. This is how training room is created [Updated first post].
 
Very well done there :)

I've got a little suggestion for you if you don't mind ^^
rather then using randomly created positions, you could use some kind of indication system, this way you do not waste space and need fewer checks for it.

I mean like:
1 room is created around the masterPos {x=3, y=3, z=1}
then we start to indicate the next, depending on if players should be able to see eachothers training rooms or not.
2 room would be like:
Lua:
local grid = 5 -- this should be the tile difference between the masterPos from each to another 5 is min in this case so rooms are next to eachother.
local index = 1 -- the room which is getting created.
then the formula would look something like this:
{x=3 + (grid * index), y=3, z=1}

I guess you get the idea, if not I'll provide you some basic code and show you what I mean :p


kind regards, Evil Hero.
 
Last edited:
Very well done there :)

I've got a little suggestion for you if you don't mind ^^
rather then using randomly created positions, you could use some kind of indication system, this way you do not waste space and need fewer checks for it.

I mean like:
1 room is created around the masterPos {x=3, y=3, z=1}
then we start to indicate the next, depending on if players should be able to see eachothers training rooms or not.
2 room would be like:
Lua:
local grid = 5 -- this should be the tile difference between the masterPos from each to another 5 is min in this case so rooms are next to eachother.
local index = 1 -- the room which is getting created.
then the formula would look something like this:
{x=3 + (grid * index), y=3, z=1}

I guess you get the idea, if not I'll provide you some basic code and show you what I mean :p


kind regards, Evil Hero.

I think I got what you mean, but to get "grid", the tile difference between the masterPos I think I would be using globalStorage to store cordinates of masterPos, I am right? But that will not collect some void space in my opinion, because rooms is cleaned after player quit. And random check is used only one time, however if I would be using globalStorage I could use only one if statement function: getGlobalStorage instead of thirty getTileItemId. Probably will edit script.
 
Here is what I was thinking
!!UPDATE!!
I've tested it and it's 100% working

functions/global.lua
Code:
roomIndex = {}

config =
{
room =
{
teleport = 1387,
ground = 406,
nortWestCorner = 1113,
southEastCorner = 1115,
wallFaceNorth = 1116,
wallFaceEast = 1114,
fire = 1484,
trainer = "Training Monk"
},
temple = {x = 3893, y = 3710, z = 6}, -- the position the player will get teleported to if he leaves the training room
startPos = {x = 100, y = 100, z = 6}, -- the top north west position from where we start to create the rooms from.
offset = 5, -- this is the space between each masterPos of the room (can't be lower then 5!)
gridX = 10, -- how much training rooms we create on one x axis
gridY = 10, -- how much training rooms we create on one y axis
gridZ = 3 -- how much layers we use therefor
-- this basicly means we can create in the grid example: 10*10*3 = 300 trainings room in this case.
}

function createTrainingRoom(pos)
local realPos = {x = pos.x - 2, y = pos.y - 2, z = pos.z}
for a = 0,4 do -- here we create the ground
for b = 0,4 do
doCreateItem(config.room.ground, 1, {x = realPos.x + a, y = realPos.y + b, z = realPos.z})
end
end
doCreateItem(config.room.nortWestCorner, 1, realPos) -- we create the north west corner wall
doCreateItem(config.room.southEastCorner, 1, {x = realPos.x + 4, y = realPos.y + 4, z = realPos.z}) -- we create the south east corner wall
for a = 1,4 do -- we create the left wall side which faces north
doCreateItem(config.room.wallFaceNorth, 1, {x = realPos.x, y = realPos.y + a, z = realPos.z})
end
for a = 1,3 do -- we create the right wall side which faces north
doCreateItem(config.room.wallFaceNorth, 1, {x = realPos.x + 4, y = realPos.y + a, z = realPos.z})
end
for a = 1,4 do -- we create the north wall side which faces east
doCreateItem(config.room.wallFaceEast, 1, {x = realPos.x + a, y = realPos.y, z = realPos.z})
end
for a = 1,3 do -- we create the south wall side which faces east
doCreateItem(config.room.wallFaceEast, 1, {x = realPos.x + a, y = realPos.y + 4, z = realPos.z})
end
doCreateItem(config.room.fire, 1, {x = realPos.x + 1, y = realPos.y + 2, z = realPos.z}) -- here we create the fire lights
doCreateItem(config.room.fire, 1, {x = realPos.x + 1, y = realPos.y + 3, z = realPos.z}) -- here we create the fire lights
doCreateItem(config.room.fire, 1, {x = realPos.x + 3, y = realPos.y + 2, z = realPos.z}) -- here we create the fire lights
doCreateItem(config.room.fire, 1, {x = realPos.x + 3, y = realPos.y + 3, z = realPos.z}) -- here we create the fire lights
doSummonCreature(config.room.trainer, {x = realPos.x + 3, y = realPos.y + 1, z = realPos.z}) -- here we create the training monsters
doSummonCreature(config.room.trainer, {x = realPos.x + 1, y = realPos.y + 1, z = realPos.z}) -- here we create the training monsters
local teleport = doCreateItem(config.room.teleport, 1, {x = realPos.x + 2, y = realPos.y + 1, z = realPos.z})
doItemSetAttribute(teleport, "aid", 8771) -- here we create the teleport to leave the room
end

function deleteTrainingRoom(pos)
local playerpos = pos
for x = playerpos.x-2, playerpos.x+2 do
for y = playerpos.y-1, playerpos.y+3 do
for z = playerpos.z, playerpos.z do
local pos = {x=x, y=y, z=z, stackpos = 253}
local thing = getThingfromPos(pos)
if thing.itemid > 0 then
doRemoveCreature(thing.uid)
end
local pos = {x=x, y=y, z=z, stackpos = 1}
local thing = getThingfromPos(pos)
if thing.itemid > 0 then
doRemoveItem(thing.uid)
end
local pos = {x=x, y=y, z=z}
local thing = getThingfromPos(pos)
if thing.itemid > 0 then
doRemoveItem(thing.uid)
end
end
end
end
    return true
end

function getNextRoom()
if roomIndex[1] ~= nil then
for a = 1, #roomIndex do
if roomIndex[a] == false then
return a
elseif #roomIndex == a then
roomIndex[#roomIndex + 1] = false
return #roomIndex
end
end
else
return 1
end
end

function getRoomPosFromIndex(id)
local indicator = {x = 0, y = 0, z = 0}
if id > config.gridX * config.gridY then
repeat
id = id - config.gridX * config.gridY
indicator.z = indicator.z + 1
until id <= config.gridX * config.gridY
end
if id > config.gridX then
repeat
id = id - config.gridY
indicator.y = indicator.y + 1
until id <= config.gridY
end
indicator.x = id
local offset = {x = indicator.x * config.offset, y = indicator.y * config.offset, z = indicator.z}
return {x = config.startPos.x + offset.x, y = config.startPos.y + offset.y, z = config.startPos.z + offset.z}
end

function getRoomIndexFromPos(pos)
local x = (pos.x - config.startPos.x) / config.offset
local y = (pos.y - config.startPos.y) / config.offset * config.gridY
local z = (pos.z - config.startPos.z) * (config.gridX * config.gridY)
return (x + y + z)
end

function setRoomInUse(id)
roomIndex[id] = true
end
function setRoomUnused(id)
roomIndex[id] = false
end

movements:
Code:
function onStepIn(cid, item, position, fromPosition)
if item.actionid == 8770 then
if getNextRoom() <= (config.gridX * config.gridY * config.gridZ) then
local currentRoom = getNextRoom()
createTrainingRoom(getRoomPosFromIndex(getNextRoom()))
doTeleportThing(cid, getRoomPosFromIndex(currentRoom), false)
setRoomInUse(currentRoom)
else
doPlayerSendCancel(cid, "All rooms are taken at the moment.")
doTeleportThing(cid, fromPosition, true)
end
elseif item.actionid == 8771 then
doTeleportThing(cid, config.temple, false)
deleteTrainingRoom(position)
setRoomUnused(getRoomIndexFromPos(fromPosition))
end
return true
end

this is a pretty basic version but could be extended with some usefull stuff such as (gm's can check with a talkaction how much rooms are used, they can also check who's inside)
will sit myself behind it and re write it some :p


kind regards, Evil Hero.
 
Last edited:
@Evil Hero

I tested ur version of this great idea, and i always have bug the first time use it, after login again this work perfectly, idk the reason :/
 
I guess you mean that the tiles and players are not getting updated properly if another player next to you is creating a room. I need to check how I solved that problem as I had that aswell.
was something at onUpdateTile, where you have to send all the spectators the new tiles.
 
Here is what I was thinking
!!UPDATE!!
I've tested it and it's 100% working

functions/global.lua
Lua:
roomIndex = {}

config =
{
	room =
	{
		teleport = 1387,
		ground = 406,
		nortWestCorner = 1113,
		southEastCorner = 1115,
		wallFaceNorth = 1116,
		wallFaceEast = 1114,
		fire = 1484,
		trainer = "Training Monk"
	},
	temple = {x = 3893, y = 3710, z = 6}, -- the position the player will get teleported to if he leaves the training room
	startPos = {x = 100, y = 100, z = 6}, -- the top north west position from where we start to create the rooms from.
	offset = 5, -- this is the space between each masterPos of the room (can't be lower then 5!)
	gridX = 10, -- how much training rooms we create on one x axis
	gridY = 10, -- how much training rooms we create on one y axis
	gridZ = 3 -- how much layers we use therefor
	-- this basicly means we can create in the grid example: 10*10*3 = 300 trainings room in this case.
}

function createTrainingRoom(pos)
local realPos = {x = pos.x - 2, y = pos.y - 2, z = pos.z}
	for a = 0,4 do -- here we create the ground
		for b = 0,4 do
			doCreateItem(config.room.ground, 1, {x = realPos.x + a, y = realPos.y + b, z = realPos.z})
		end
	end
	doCreateItem(config.room.nortWestCorner, 1, realPos) -- we create the north west corner wall
	doCreateItem(config.room.southEastCorner, 1, {x = realPos.x + 4, y = realPos.y + 4, z = realPos.z}) -- we create the south east corner wall
	for a = 1,4 do -- we create the left wall side which faces north
		doCreateItem(config.room.wallFaceNorth, 1, {x = realPos.x, y = realPos.y + a, z = realPos.z})
	end
	for a = 1,3 do -- we create the right wall side which faces north
		doCreateItem(config.room.wallFaceNorth, 1, {x = realPos.x + 4, y = realPos.y + a, z = realPos.z})
	end
	for a = 1,4 do -- we create the north wall side which faces east
		doCreateItem(config.room.wallFaceEast, 1, {x = realPos.x + a, y = realPos.y, z = realPos.z})
	end
	for a = 1,3 do -- we create the south wall side which faces east
		doCreateItem(config.room.wallFaceEast, 1, {x = realPos.x + a, y = realPos.y + 4, z = realPos.z})
	end
	doCreateItem(config.room.fire, 1, {x = realPos.x + 1, y = realPos.y + 2, z = realPos.z}) -- here we create the fire lights
	doCreateItem(config.room.fire, 1, {x = realPos.x + 1, y = realPos.y + 3, z = realPos.z}) -- here we create the fire lights
	doCreateItem(config.room.fire, 1, {x = realPos.x + 3, y = realPos.y + 2, z = realPos.z}) -- here we create the fire lights
	doCreateItem(config.room.fire, 1, {x = realPos.x + 3, y = realPos.y + 3, z = realPos.z}) -- here we create the fire lights
	doSummonCreature(config.room.trainer, {x = realPos.x + 3, y = realPos.y + 1, z = realPos.z}) -- here we create the training monsters
	doSummonCreature(config.room.trainer, {x = realPos.x + 1, y = realPos.y + 1, z = realPos.z}) -- here we create the training monsters
	local teleport = doCreateItem(config.room.teleport, 1, {x = realPos.x + 2, y = realPos.y + 1, z = realPos.z})
	doItemSetAttribute(teleport, "aid", 8771) -- here we create the teleport to leave the room
end

function deleteTrainingRoom(pos)
local playerpos = pos
	for x = playerpos.x-2, playerpos.x+2 do
		for y = playerpos.y-1, playerpos.y+3 do
			for z = playerpos.z, playerpos.z do
				local pos = {x=x, y=y, z=z, stackpos = 253}
				local thing = getThingfromPos(pos)
				if thing.itemid > 0 then
					doRemoveCreature(thing.uid)
				end
				local pos = {x=x, y=y, z=z, stackpos = 1}
				local thing = getThingfromPos(pos)
				if thing.itemid > 0 then
					doRemoveItem(thing.uid)
				end
				local pos = {x=x, y=y, z=z}
				local thing = getThingfromPos(pos)
				if thing.itemid > 0 then
					doRemoveItem(thing.uid)
				end
			end
		end
	end
    return true
end

function getNextRoom()
	if roomIndex[1] ~= nil then
		for a = 1, #roomIndex do
			if roomIndex[a] == false then
				return a
			elseif #roomIndex == a then
				roomIndex[#roomIndex + 1] = false
				return #roomIndex
			end
		end
	else
		return 1
	end
end

function getRoomPosFromIndex(id)
local indicator = {x = 0, y = 0, z = 0}
	if id > config.gridX * config.gridY then
		repeat
			id = id - config.gridX * config.gridY
			indicator.z = indicator.z + 1
		until id <= config.gridX * config.gridY
	end
	if id > config.gridX then
		repeat
			id = id - config.gridY
			indicator.y = indicator.y + 1
		until id <= config.gridY
	end
	indicator.x = id
	local offset = {x = indicator.x * config.offset, y = indicator.y * config.offset, z = indicator.z}
	return {x = config.startPos.x + offset.x, y = config.startPos.y + offset.y, z = config.startPos.z + offset.z}
end

function getRoomIndexFromPos(pos)
	local x = (pos.x - config.startPos.x) / config.offset
	local y = (pos.y - config.startPos.y) / config.offset * config.gridY
	local z = (pos.z - config.startPos.z) * (config.gridX * config.gridY)
	return (x + y + z)
end
	
function setRoomInUse(id)
	roomIndex[id] = true
end
function setRoomUnused(id)
	roomIndex[id] = false
end

movements:
Lua:
function onStepIn(cid, item, position, fromPosition)
	if item.actionid == 8770 then
		if getNextRoom() <= (config.gridX * config.gridY * config.gridZ) then
			local currentRoom = getNextRoom()
			createTrainingRoom(getRoomPosFromIndex(getNextRoom()))
			doTeleportThing(cid, getRoomPosFromIndex(currentRoom), false)
			setRoomInUse(currentRoom)
		else
			doPlayerSendCancel(cid, "All rooms are taken at the moment.")
			doTeleportThing(cid, fromPosition, true)
		end
	elseif item.actionid == 8771 then
		doTeleportThing(cid, config.temple, false)
		deleteTrainingRoom(position)
		setRoomUnused(getRoomIndexFromPos(fromPosition))
	end
	return true
end

this is a pretty basic version but could be extended with some usefull stuff such as (gm's can check with a talkaction how much rooms are used, they can also check who's inside)
will sit myself behind it and re write it some :p


kind regards, Evil Hero.

God damn this guy is insane.... Wish I could script like this.
 
Back
Top