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

Feature Loot Channel

xxgoosexx

GoosioOT
Joined
Jul 10, 2007
Messages
298
Reaction score
2
Something I like to use because I am too lazy to open corpses.
Nothing too hard that a decent coder couldn't have done. Basically just the broadcastPartyLoot function from SVN changed into broadcastPlayerLoot and a new channel created..anyways here it goes..(Works for both 0.2 and 0.3 TFS)


UPDATED: Players not speaking in channel source was changed
CHANGE CHANNEL_LOOT to 0x10 in TFS 0.2

For 0.3 (unless you have channels in enums for 0.2 as well)
enums.h
search
Code:
enum Channels_t
and add
PHP:
	CHANNEL_LOOT = 0x10

chat.cpp
search for
Code:
		else if(player->getLevel() < 2 && channelId > CHANNEL_GUILD && channelId < CHANNEL_PARTY)
		{
			player->sendCancel("You may not speak into channels as long as you are on level 1.");
			return true;
		}
and after it add
PHP:
		else if(channelId == CHANNEL_LOOT)
		{
			player->sendCancel("You may not speak in this channel.");
			return true;
		}
This makes it so players cannot talk in this channel (thanks to elf)

search for
Code:
	m_partyChannels.clear();
and add
PHP:
	for(LootChannelMap::iterator it = m_lootChannels.begin(); it != m_lootChannels.end(); ++it)
		delete it->second;

	m_lootChannels.clear();

go down like 30 lines (chat::createchannel) and after
Code:
		case CHANNEL_PARTY:
		{
			ChatChannel* newChannel = NULL;
			if(player->getParty() && (newChannel = new ChatChannel(channelId, "Party")))
				m_partyChannels[player->getParty()] = newChannel;

			return newChannel;
		}

add
PHP:
		case CHANNEL_LOOT:
		{
			ChatChannel* newChannel = NULL;
			if(player->getLoot() && (newChannel = new ChatChannel(channelId, "Loot")))
				m_lootChannels[player->getLoot()] = newChannel;

			return newChannel;
		}

then in chat::deletechannel add
PHP:
		case CHANNEL_LOOT:
		{
			LootChannelMap::iterator it = m_lootChannels.find(player->getLoot());
			if(it == m_lootChannels.end())
				return false;

			delete it->second;
			m_lootChannels.erase(it);
			return true;
		}

in chat::getchannellist add

PHP:
	if(player->getLoot())
	{
		ChatChannel* channel = getChannel(player, CHANNEL_LOOT);
		if(channel)
			list.push_back(channel);
		else if((channel = createChannel(player, CHANNEL_LOOT)))
			list.push_back(channel);
	}

finally in chat::getchannel add
PHP:
	if(channelId == CHANNEL_LOOT)
	{
		if(!player->getLoot())
			return NULL;
		LootChannelMap::iterator it = m_lootChannels.find(player->getLoot());
		if(it != m_lootChannels.end())
			return it->second;
	
		return NULL;
	}

chat.h
towards the end in
Code:
private:
add
PHP:
		typedef std::map<uint32_t, ChatChannel*> LootChannelMap;
and after it
PHP:
		LootChannelMap m_lootChannels;


player.cpp
search for
Code:
	ghostMode = false;
and add after it
PHP:
	showLoot = false;

and at the bottom of the page add
PHP:
void Player::broadcastPlayerLoot(const std::string& monster, const ItemVector& items)
{
	std::stringstream s;
	s << "Loot of " << monster << ": ";
	if(items.size())
	{
		for(ItemVector::const_reverse_iterator rit = items.rbegin(); rit != items.rend(); ++rit)
		{
			s << (*rit)->getNameDescription();
			if((*rit) != items.front())
				s << ", ";
		}
	}
	else
		s << "none";

	s << ".";
	sendChannelMessage("", s.str().c_str(), SPEAK_CHANNEL_W, CHANNEL_LOOT);
}

player.h

in the public: (i put mine after the ghost stuff) add
PHP:
		void switchGetLoot() {showLoot = !showLoot;}
		bool getLoot() const {return showLoot;}

also add in public: (i added mine at end of it above protected:)

PHP:
		void broadcastPlayerLoot(const std::string& monster, const ItemVector& items);

search for
Code:
bool ghostMode;

and add after it
PHP:
		bool showLoot;

monsters.cpp

search for
Code:
		if((owner = g_game.getPlayerByID(ownerId)) && owner->getParty())
			owner->getParty()->broadcastPartyLoot(name, itemVector);

and add after it
PHP:
		if((owner = g_game.getPlayerByID(ownerId)) && owner->getLoot())
			owner->broadcastPlayerLoot(name, itemVector);


talkactions.cpp [0.3]

at the bottom add
PHP:
bool TalkAction::showLoot(Player* player, const std::string& cmd, const std::string& param)
{
	player->switchGetLoot();

	char buffer[90];
	sprintf(buffer, "You have %s the loot channel.", (player->getLoot() ? "enabled" : "disabled"));
	player->sendTextMessage(MSG_INFO_DESCR, buffer);

	char channel[90];
	sprintf(channel, "The loot channel has been %s.", (player->getLoot () ? "activated" : "deactivated"));
	player->sendChannelMessage("", channel, SPEAK_CHANNEL_R1, CHANNEL_LOOT);

	return true;
}

commands.cpp [0.2]
PHP:
bool Commands::showLoot(Creature* creature, const std::string& cmd, const std::string& param)
{
	Player* player = creature->getPlayer();
	player->switchGetLoot();

	char buffer[90];
	sprintf(buffer, "You have %s the loot channel.", (player->getLoot() ? "enabled" : "disabled"));
	player->sendTextMessage(MSG_INFO_DESCR, buffer);

	char channel[90];
	sprintf(channel, "The loot channel has been %s.", (player->getLoot () ? "activated" : "deactivated"));
	player->sendChannelMessage("", channel, SPEAK_CHANNEL_R1, 0x10);

	return true;
}

I did not finish the talkactions.h / commands.h due to lack of caring (they aren't hard to finish oO)

 
Last edited:
You could do it easier way. Do not allow players to speak on CHANNEL_LOOT, and player->sendChannelMessage.

thanks, worked and code was updated ++rep

probably a little different still (players who can't be muted can still message in there to other players)
but it tells players they can't chat now, and words in there arent spoken in default now
 
Ahh nice, great code ^^
 
Nice code... but what do we do if none of the following code to be found is not there......?

Like you said search for enum Channels_t in enums.h.... there is no such code in that file at all!!
 
Nice code... but what do we do if none of the following code to be found is not there......?

Like you said search for enum Channels_t in enums.h.... there is no such code in that file at all!!

what version are you using? if you are using 0.2 it won't be there, then use 0x10 instead of CHANNEL_LOOT
 
Yes they are:

PHP:
enum Channels_t
{
	CHANNEL_GUILD = 0x00,
	CHANNEL_STAFF = 0x01,
	CHANNEL_COUNSELOR = 0x02,
	CHANNEL_RVR = 0x03,
	CHANNEL_GAMECHAT = 0x04,
	CHANNEL_TRADE = 0x05,
	CHANNEL_RLCHAT = 0x06,
	CHANNEL_TRADEROOK = 0x07,
	CHANNEL_PARTY = 0x08,
	CHANNEL_HELP = 0x09,
	CHANNEL_VIPCHAT = 0x10,
	CHANNEL_PRIVATE = 0xFFFF
};
 
Yes they are:

PHP:
enum Channels_t
{
	CHANNEL_GUILD = 0x00,
	CHANNEL_STAFF = 0x01,
	CHANNEL_COUNSELOR = 0x02,
	CHANNEL_RVR = 0x03,
	CHANNEL_GAMECHAT = 0x04,
	CHANNEL_TRADE = 0x05,
	CHANNEL_RLCHAT = 0x06,
	CHANNEL_TRADEROOK = 0x07,
	CHANNEL_PARTY = 0x08,
	CHANNEL_HELP = 0x09,
	CHANNEL_VIPCHAT = 0x10,
	CHANNEL_PRIVATE = 0xFFFF
};

in my enums.h (0.2) they arent in there, it may be older?, but its not there
 
newest 0.3 rev of the tfs server... Not there.. neither the channel nor that code.. any other ideas?

Here is the Enums.h i have for the tfs...

Code:
//////////////////////////////////////////////////////////////////////
// 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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//////////////////////////////////////////////////////////////////////

#ifndef __OTSERV_ENUMS_H__
#define __OTSERV_ENUMS_H__
#include <string>
#include <list>

enum DatabaseEngine_t
{
	DATABASE_ENGINE_NONE = 0,
	DATABASE_ENGINE_MYSQL = 1,
	DATABASE_ENGINE_SQLITE = 2,
	DATABASE_ENGINE_POSTGRESQL = 3,
	DATABASE_ENGINE_ODBC = 4
};

enum PasswordType_t
{
	PASSWORD_TYPE_PLAIN = 0,
	PASSWORD_TYPE_MD5 = 1,
	PASSWORD_TYPE_SHA1 = 2
};

enum GuildLevel_t
{
	GUILDLEVEL_MEMBER = 1,
	GUILDLEVEL_VICE = 2,
	GUILDLEVEL_LEADER = 3
};

enum OperatingSystem_t
{
	CLIENTOS_LINUX = 0x01,
	CLIENTOS_WINDOWS = 0x02
};

enum RaceType_t
{
	RACE_NONE	= 0,
	RACE_VENOM 	= 1,
	RACE_BLOOD	= 2,
	RACE_UNDEAD	= 3,
	RACE_FIRE	= 4
};

enum CombatType_t
{
	COMBAT_NONE		= 0,
	COMBAT_PHYSICALDAMAGE	= 1,
	COMBAT_ENERGYDAMAGE	= 2,
	COMBAT_EARTHDAMAGE	= 4,
	COMBAT_FIREDAMAGE	= 8,
	COMBAT_UNDEFINEDDAMAGE	= 16,
	COMBAT_LIFEDRAIN	= 32,
	COMBAT_MANADRAIN	= 64,
	COMBAT_HEALING		= 128,
	COMBAT_DROWNDAMAGE	= 256,
	COMBAT_ICEDAMAGE	= 512,
	COMBAT_HOLYDAMAGE	= 1024,
	COMBAT_DEATHDAMAGE      = 2048
};

enum CombatParam_t
{
	COMBATPARAM_COMBATTYPE = 1,
	COMBATPARAM_EFFECT = 2,
	COMBATPARAM_DISTANCEEFFECT = 3,
	COMBATPARAM_BLOCKEDBYSHIELD = 4,
	COMBATPARAM_BLOCKEDBYARMOR = 5,
	COMBATPARAM_TARGETCASTERORTOPMOST = 6,
	COMBATPARAM_CREATEITEM = 7,
	COMBATPARAM_AGGRESSIVE = 8,
	COMBATPARAM_DISPEL = 9,
	COMBATPARAM_USECHARGES = 10
};

enum CallBackParam_t
{
	CALLBACKPARAM_LEVELMAGICVALUE = 1,
	CALLBACKPARAM_SKILLVALUE = 2,
	CALLBACKPARAM_TARGETTILECALLBACK = 3,
	CALLBACKPARAM_TARGETCREATURECALLBACK = 4
};

enum ConditionParam_t
{
	CONDITIONPARAM_OWNER = 1,
	CONDITIONPARAM_TICKS = 2,
	//CONDITIONPARAM_OUTFIT = 3,

	CONDITIONPARAM_HEALTHGAIN = 4,
	CONDITIONPARAM_HEALTHTICKS = 5,
	CONDITIONPARAM_MANAGAIN = 6,
	CONDITIONPARAM_MANATICKS = 7,
	CONDITIONPARAM_DELAYED = 8,
	CONDITIONPARAM_SPEED = 9,
	CONDITIONPARAM_LIGHT_LEVEL = 10,
	CONDITIONPARAM_LIGHT_COLOR = 11,
	CONDITIONPARAM_SOULGAIN = 12,
	CONDITIONPARAM_SOULTICKS = 13,
	CONDITIONPARAM_MINVALUE = 14,
	CONDITIONPARAM_MAXVALUE = 15,
	CONDITIONPARAM_STARTVALUE = 16,
	CONDITIONPARAM_TICKINTERVAL = 17,
	CONDITIONPARAM_FORCEUPDATE = 18,
	CONDITIONPARAM_SKILL_MELEE = 19,
	CONDITIONPARAM_SKILL_FIST = 20,
	CONDITIONPARAM_SKILL_CLUB = 21,
	CONDITIONPARAM_SKILL_SWORD = 22,
	CONDITIONPARAM_SKILL_AXE = 23,
	CONDITIONPARAM_SKILL_DISTANCE = 24,
	CONDITIONPARAM_SKILL_SHIELD = 25,
	CONDITIONPARAM_SKILL_FISHING = 26,
	CONDITIONPARAM_STAT_MAXHEALTH = 27,
	CONDITIONPARAM_STAT_MAXMANA = 28,
	CONDITIONPARAM_STAT_SOUL = 29,
	CONDITIONPARAM_STAT_MAGICLEVEL = 30,
	CONDITIONPARAM_STAT_MAXHEALTHPERCENT = 31,
	CONDITIONPARAM_STAT_MAXMANAPERCENT = 32,
	CONDITIONPARAM_STAT_SOULPERCENT = 33,
	CONDITIONPARAM_STAT_MAGICLEVELPERCENT = 34,
	CONDITIONPARAM_PERIODICDAMAGE = 35,
	CONDITIONPARAM_SKILL_SOUND = 36
};

enum BlockType_t
{
	BLOCK_NONE = 0,
	BLOCK_DEFENSE,
	BLOCK_ARMOR,
	BLOCK_IMMUNITY
};

enum skills_t
{
	SKILL_FIRST = 0,
	SKILL_FIST = SKILL_FIRST,
	SKILL_CLUB = 1,
	SKILL_SWORD = 2,
	SKILL_AXE = 3,
	SKILL_DIST = 4,
	SKILL_SHIELD = 5,
	SKILL_FISH = 6,
	MAGLEVEL = 7,
	LEVEL = 8,
	SKILL_LAST = SKILL_FISH
};

enum stats_t
{
	STAT_FIRST = 0,
	STAT_MAXHEALTH = STAT_FIRST,
	STAT_MAXMANA,
	STAT_SOUL,
	STAT_MAGICLEVEL,
	STAT_LAST = STAT_MAGICLEVEL
};

enum lossTypes_t
{
	LOSS_FIRST = 0,
	LOSS_EXPERIENCE = LOSS_FIRST,
	LOSS_MANASPENT = 1,
	LOSS_SKILLTRIES = 2,
	LOSS_ITEMS = 3,
	LOSS_LAST = LOSS_ITEMS
};

enum formulaType_t
{
	FORMULA_UNDEFINED = 0,
	FORMULA_LEVELMAGIC = 1,
	FORMULA_SKILL = 2,
	FORMULA_VALUE = 3
};

enum ConditionId_t
{
	CONDITIONID_DEFAULT = -1,
	CONDITIONID_COMBAT = 0,
	CONDITIONID_HEAD = 1,
	CONDITIONID_NECKLACE = 2,
	CONDITIONID_BACKPACK = 3,
	CONDITIONID_ARMOR = 4,
	CONDITIONID_RIGHT = 5,
	CONDITIONID_LEFT = 6,
	CONDITIONID_LEGS = 7,
	CONDITIONID_FEET = 8,
	CONDITIONID_RING = 9,
	CONDITIONID_AMMO = 10
};

enum PlayerSex_t
{
	PLAYERSEX_FEMALE = 0,
	PLAYERSEX_MALE = 1
};

enum CharacterTypes_t
{
	PLAYER_MALE_1 = 0x80,
	PLAYER_MALE_2 = 0x81,
	PLAYER_MALE_3 = 0x82,
	PLAYER_MALE_4 = 0x83,
	PLAYER_MALE_5 = 0x84,
	PLAYER_MALE_6 = 0x85,
	PLAYER_MALE_7 = 0x86,
	PLAYER_FEMALE_1 = 0x88,
	PLAYER_FEMALE_2 = 0x89,
	PLAYER_FEMALE_3 = 0x8A,
	PLAYER_FEMALE_4 = 0x8B,
	PLAYER_FEMALE_5 = 0x8C,
	PLAYER_FEMALE_6 = 0x8D,
	PLAYER_FEMALE_7 = 0x8E,
};

struct Outfit_t
{
	Outfit_t()
	{
		lookHead   = 0;
		lookBody   = 0;
		lookLegs   = 0;
		lookFeet   = 0;
		lookType   = 0;
		lookTypeEx = 0;
		lookAddons = 0;
	}

	uint16_t lookType;
	uint16_t lookTypeEx;
	uint8_t lookHead;
	uint8_t lookBody;
	uint8_t lookLegs;
	uint8_t lookFeet;
	uint8_t lookAddons;
};

struct LightInfo
{
	uint32_t level;
	uint32_t color;
	LightInfo()
	{
		level = 0;
		color = 0;
	}
	LightInfo(uint32_t _level, uint32_t _color)
	{
		level = _level;
		color = _color;
	}
};

struct ShopInfo
{
	uint32_t itemId;
	uint32_t subType;
	uint32_t buyPrice;
	uint32_t sellPrice;
	std::string itemName;

	ShopInfo()
	{
		itemId = 0;
		subType = 1;
		buyPrice = 0;
		sellPrice = 0;
		itemName = "";
	}

	ShopInfo(uint32_t _itemId, int32_t _subType = 0, uint32_t _buyPrice = 0, uint32_t _sellPrice = 0,
		const std::string& _itemName = "") : itemId(_itemId), subType(_subType), buyPrice(_buyPrice),
		sellPrice(_sellPrice), itemName(_itemName) {}
};

typedef std::list<ShopInfo> ShopInfoList;
#endif
Same thing for the rest..
here is chat.cpp
Code:
//////////////////////////////////////////////////////////////////////
// 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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//////////////////////////////////////////////////////////////////////
#include "otpch.h"

#include "chat.h"
#include "configmanager.h"
#include "player.h"
#include "game.h"
#include "iologindata.h"

extern ConfigManager g_config;
extern Game g_game;

PrivateChatChannel::PrivateChatChannel(uint16_t channelId, std::string channelName) :
	ChatChannel(channelId, channelName)
{
	m_owner = 0;
}

bool PrivateChatChannel::isInvited(const Player* player)
{
	if(!player)
		return false;

	if(player->getGUID() == getOwner())
		return true;

	InvitedMap::iterator it = m_invites.find(player->getGUID());
	if(it != m_invites.end())
		return true;

	return false;
}

bool PrivateChatChannel::addInvited(Player* player)
{
	InvitedMap::iterator it = m_invites.find(player->getGUID());
	if(it != m_invites.end())
		return false;

	m_invites[player->getGUID()] = player;
	return true;
}

bool PrivateChatChannel::removeInvited(Player* player)
{
	InvitedMap::iterator it = m_invites.find(player->getGUID());
	if(it == m_invites.end())
		return false;

	m_invites.erase(it);
	return true;
}

void PrivateChatChannel::invitePlayer(Player* player, Player* invitePlayer)
{
	if(player != invitePlayer && addInvited(invitePlayer))
	{
		std::string msg;
		msg = player->getName();
		msg += " invites you to ";
		msg += (player->getSex() == PLAYERSEX_FEMALE ? "her" : "his");
		msg += " private chat channel.";
		invitePlayer->sendTextMessage(MSG_INFO_DESCR, msg.c_str());

		msg = invitePlayer->getName();
		msg += " has been invited.";
		player->sendTextMessage(MSG_INFO_DESCR, msg.c_str());
	}
}

void PrivateChatChannel::excludePlayer(Player* player, Player* excludePlayer)
{
	if(player != excludePlayer && removeInvited(excludePlayer))
	{
		removeUser(excludePlayer);

		std::string msg;
		msg = excludePlayer->getName();
		msg += " has been excluded.";
		player->sendTextMessage(MSG_INFO_DESCR, msg.c_str());

		excludePlayer->sendClosePrivate(getId());
	}
}

void PrivateChatChannel::closeChannel()
{
	for(UsersMap::iterator cit = m_users.begin(); cit != m_users.end(); ++cit)
	{
		if(Player* toPlayer = cit->second->getPlayer())
			toPlayer->sendClosePrivate(getId());
	}
}

ChatChannel::ChatChannel(uint16_t channelId, std::string channelName)
{
	m_id = channelId;
	m_name = channelName;
}

bool ChatChannel::addUser(Player* player)
{
	UsersMap::iterator it = m_users.find(player->getID());
	if(it != m_users.end())
		return false;

	switch(m_id)
	{
		case 0x00:
		{
			uint32_t playerId = player->getID();
			uint32_t guildId = player->getGuildId();
			if(IOGuild::getInstance()->getMotd(player->getGuildId()).length())
				Scheduler::getScheduler().addEvent(createSchedulerTask(150, boost::bind(&Game::sendGuildMotd, &g_game, playerId, guildId)));
			break;
		}

		case 0x01:
			if(!player->hasCustomFlag(PlayerCustomFlag_CanSeeStaffChannel))
				return false;
			break;

		case 0x02:
			if(!player->hasCustomFlag(PlayerCustomFlag_CanSeeCounsellorChannel))
				return false;
			break;

		case 0x03:
			if(!player->hasFlag(PlayerFlag_CanAnswerRuleViolations))
				return false;
			break;

		case 0x05:
			if(!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) && player->getVocationId() == 0)
				return false;
			break;

		case 0x06:
			if(!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) && player->getVocationId() != 0)
				return false;
			break;
	}

	m_users[player->getID()] = player;
	return true;
}

bool ChatChannel::removeUser(Player* player)
{
	UsersMap::iterator it = m_users.find(player->getID());
	if(it == m_users.end())
		return false;

	m_users.erase(it);
	return true;
}

bool ChatChannel::talk(Player* fromPlayer, SpeakClasses type, const std::string& text, uint32_t time /*= 0*/)
{
	if(!fromPlayer->hasFlag(PlayerFlag_CannotBeMuted) && (m_id == 0x05 || m_id == 0x06))
	{
		Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_TRADETICKS, 120000, 0);
		fromPlayer->addCondition(condition);
	}

	bool success = false;
	Player* tmpPlayer = NULL;
	for(UsersMap::iterator it = m_users.begin(); it != m_users.end(); ++it)
	{
		if((tmpPlayer = it->second->getPlayer()))
		{
			tmpPlayer->sendToChannel(fromPlayer, type, text, m_id, time);
			success = true;
		}
	}
	return success;
}

Chat::Chat()
{
	// Create the default channels
	ChatChannel *newChannel;

	newChannel = new ChatChannel(0x01, "Staff");
	if(newChannel)
		m_normalChannels[0x01] = newChannel;

	newChannel = new ChatChannel(0x02, "Counsellor");
	if(newChannel)
		m_normalChannels[0x02] = newChannel;

	newChannel = new ChatChannel(0x03, "Rule Violations");
	if(newChannel)
		m_normalChannels[0x03] = newChannel;

	newChannel = new ChatChannel(0x04, "Game-Chat");
	if(newChannel)
		m_normalChannels[0x04] = newChannel;

	newChannel = new ChatChannel(0x05, "Trade");
	if(newChannel)
		m_normalChannels[0x05] = newChannel;

	newChannel = new ChatChannel(0x06, "Trade-Rookgaard");
	if(newChannel)
		m_normalChannels[0x06] = newChannel;

	newChannel = new ChatChannel(0x07, "RL-Chat");
	if(newChannel)
		m_normalChannels[0x07] = newChannel;

	newChannel = new ChatChannel(0x08, "Help");
	if(newChannel)
		m_normalChannels[0x08] = newChannel;

	newChannel = new PrivateChatChannel(0xFFFF, "Private Chat Channel");
	if(newChannel)
		dummyPrivate = newChannel;
}

Chat::~Chat()
{
	delete dummyPrivate;

	for(NormalChannelMap::iterator it = m_normalChannels.begin(); it != m_normalChannels.end(); ++it)
		delete it->second;
	m_normalChannels.clear();

	for(GuildChannelMap::iterator it = m_guildChannels.begin(); it != m_guildChannels.end(); ++it)
		delete it->second;
	m_guildChannels.clear();

	for(PrivateChannelMap::iterator it = m_privateChannels.begin(); it != m_privateChannels.end(); ++it)
		delete it->second;
	m_privateChannels.clear();
}

ChatChannel* Chat::createChannel(Player* player, uint16_t channelId)
{
	if(getChannel(player, channelId))
		return NULL;

	if(channelId == 0x00)
	{
		ChatChannel* newChannel = new ChatChannel(channelId, player->getGuildName());
		if(!newChannel)
			return NULL;

		m_guildChannels[player->getGuildId()] = newChannel;
		return newChannel;
	}
	else if(channelId == 0xFFFF)
	{
		//only 1 private channel for each premium player
		if(!player->isPremium() || getPrivateChannel(player))
			return NULL;

		//find a free private channel slot
		for(uint16_t i = 100; i < 10000; ++i)
		{
			if(m_privateChannels.find(i) == m_privateChannels.end())
			{
				PrivateChatChannel* newChannel = new PrivateChatChannel(i, player->getName() + "'s Channel");
				if(!newChannel)
					return NULL;

				newChannel->setOwner(player->getGUID());

				m_privateChannels[i] = newChannel;
				return newChannel;
			}
		}
	}
	return NULL;
}

bool Chat::deleteChannel(Player* player, uint16_t channelId)
{
	if(channelId == 0x00)
	{
		GuildChannelMap::iterator it = m_guildChannels.find(player->getGuildId());
		if(it == m_guildChannels.end())
			return false;

		delete it->second;
		m_guildChannels.erase(it);
		return true;
	}
	else
	{
		PrivateChannelMap::iterator it = m_privateChannels.find(channelId);
		if(it == m_privateChannels.end())
			return false;

		it->second->closeChannel();

		delete it->second;
		m_privateChannels.erase(it);
		return true;
	}
	return false;
}

bool Chat::addUserToChannel(Player* player, uint16_t channelId)
{
	ChatChannel* channel = getChannel(player, channelId);
	if(!channel || !player)
		return false;

	return channel->addUser(player);
}

bool Chat::removeUserFromChannel(Player* player, uint16_t channelId)
{
	ChatChannel* channel = getChannel(player, channelId);
	if(!channel || !player)
		return false;

	if(channel->removeUser(player))
	{
		if(channel->getOwner() == player->getGUID())
			deleteChannel(player, channelId);
		return true;
	}
	else
		return false;
}

void Chat::removeUserFromAllChannels(Player* player)
{
	if(!player)
		return;

	ChannelList list = getChannelList(player);
	while(list.size())
	{
		ChatChannel* channel = list.front();
		list.pop_front();
		channel->removeUser(player);
		if(channel->getOwner() == player->getGUID())
			deleteChannel(player, channel->getId());
	}
}

bool Chat::talkToChannel(Player* player, SpeakClasses type, const std::string& text, uint16_t channelId)
{
	ChatChannel* channel = getChannel(player, channelId);
	if(!channel || !player)
		return false;

	if(!player->hasFlag(PlayerFlag_CannotBeMuted))
	{
		if(player->hasCondition(CONDITION_TRADETICKS) && (channelId == 0x05 || channelId == 0x06))
		{
			player->sendCancel("You may only place one offer in two minutes.");
			return false;
		}
		else if(player->getLevel() < 2 && channelId < 0x08)
		{
			player->sendCancel("You may not speak into channels as long as you are on level 1.");
			return false;
		}
	}

	if(channelId == 0x00)
	{
		if(g_config.getBool(ConfigManager::INGAME_GUILD_MANAGEMENT))
		{
			if(text == "!disband" || text.substr(0, 7) == "!invite" || text == "!leave" || text.substr(0, 5) == "!kick" || text.substr(0, 7) == "!revoke" || text.substr(0, 7) == "!demote" || text.substr(0, 8) == "!promote" || text.substr(0, 15) == "!passleadership" || text.substr(0, 5) == "!nick" || text.substr(0, 12) == "!setrankname" || text.substr(0, 8) == "!setmotd" || text == "!cleanmotd" || text == "!commands")
			{
				if(player->getGuildId())
				{
					if(IOGuild::getInstance()->guildExists(player->getGuildId()))
					{
						char buffer[350];
						ChatChannel* guildChannel = getChannel(player, 0x00);
						if(!guildChannel)
							return false;

						if(text == "!disband")
						{
							if(player->getGuildLevel() == GUILDLEVEL_LEADER)
							{
								uint32_t guildId = player->getGuildId();
								guildChannel->talk(player, SPEAK_CHANNEL_R2, "The guild has been disbanded.");
								IOGuild::getInstance()->disbandGuild(guildId);
							}
							else
								player->sendCancel("You are not the leader of your guild.");
						}
						else if(text.substr(0, 7) == "!invite")
						{
							if(player->getGuildLevel() > GUILDLEVEL_MEMBER)
							{
								if(text.length() > 8)
								{
									std::string param = text.substr(8);
									trimString(param);
									Player* paramPlayer = g_game.getPlayerByName(param);
									if(paramPlayer)
									{
										if(paramPlayer->getGuildId() == 0)
										{
											if(!paramPlayer->isInvitedToGuild(player->getGuildId()))
											{
												sprintf(buffer, "%s has invited you to join the guild, %s.", player->getName().c_str(), player->getGuildName().c_str());
												paramPlayer->sendTextMessage(MSG_INFO_DESCR, buffer);
												sprintf(buffer, "%s has invited %s to the guild.", player->getName().c_str(), paramPlayer->getName().c_str());
												guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
												paramPlayer->invitedToGuildsList.push_back(player->getGuildId());
											}
											else
												player->sendCancel("A player with that name has already been invited to your guild.");
										}
										else
											player->sendCancel("A player with that name is already in a guild.");
									}
									else if(IOLoginData::getInstance()->playerExists(param))
									{
										uint32_t guid;
										IOLoginData::getInstance()->getGuidByName(guid, param);
										if(!IOGuild::getInstance()->hasGuild(guid))
										{
											if(!IOGuild::getInstance()->isInvitedToGuild(guid, player->getGuildId()))
											{
												if(IOGuild::getInstance()->guildExists(player->getGuildId()))
												{
													IOGuild::getInstance()->invitePlayerToGuild(guid, player->getGuildId());
													sprintf(buffer, "%s has invited %s to the guild.", player->getName().c_str(), param.c_str());
													guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
												}
												else
													player->sendCancel("Your guild does not exist anymore.");
											}
											else
												player->sendCancel("A player with that name has already been invited to your guild.");
										}
										else
											player->sendCancel("A player with that name is already in a guild.");
									}
									else
										player->sendCancel("A player with that name does not exist.");
								}
								else
									player->sendCancel("Invalid guildcommand parameters.");
							}
							else
								player->sendCancel("You don't have rights to invite players to your guild.");
						}
						else if(text == "!leave")
						{
							if(player->getGuildLevel() < GUILDLEVEL_LEADER)
							{
								sprintf(buffer, "%s has left the guild.", player->getName().c_str());
								guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
								player->resetGuildInformation();
							}
							else
								player->sendCancel("You cannot leave your guild because you are the leader of it, you have to pass the leadership to another member of your guild or disband the guild.");
						}
						else if(text.substr(0, 7) == "!revoke")
						{
							if(player->getGuildLevel() > GUILDLEVEL_MEMBER)
							{
								if(text.length() > 8)
								{
									std::string param = text.substr(8);
									trimString(param);
									Player* paramPlayer = g_game.getPlayerByName(param);
									if(paramPlayer)
									{
										if(paramPlayer->getGuildId() == 0)
										{
											InvitedToGuildsList::iterator it = std::find(paramPlayer->invitedToGuildsList.begin(),paramPlayer->invitedToGuildsList.end(), player->getGuildId());
											if(it != paramPlayer->invitedToGuildsList.end())
											{
												sprintf(buffer, "%s has revoked your invite to %s guild.", player->getName().c_str(), (player->getSex() == PLAYERSEX_FEMALE ? "her" : "his"));
												paramPlayer->sendTextMessage(MSG_INFO_DESCR, buffer);
												sprintf(buffer, "%s has revoked the guildinvite of %s.", player->getName().c_str(), paramPlayer->getName().c_str());
												guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
												paramPlayer->invitedToGuildsList.erase(it);
												return true;
											}
											else
												player->sendCancel("A player with that name is not invited to your guild.");
										}
										else
											player->sendCancel("A player with that name is already in a guild.");
									}
									else if(IOLoginData::getInstance()->playerExists(param))
									{
										uint32_t guid;
										IOLoginData::getInstance()->getGuidByName(guid, param);
										if(IOGuild::getInstance()->isInvitedToGuild(guid, player->getGuildId()))
										{
											if(IOGuild::getInstance()->guildExists(player->getGuildId()))
											{
												sprintf(buffer, "%s has revoked the guildinvite of %s.", player->getName().c_str(), param.c_str());
												guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
												IOGuild::getInstance()->revokeGuildInvite(guid, player->getGuildId());
											}
											else
												player->sendCancel("It seems like your guild does not exist anymore.");
										}
										else
											player->sendCancel("A player with that name is not invited to your guild.");
									}
									else
										player->sendCancel("A player with that name does not exist.");
								}
								else
									player->sendCancel("Invalid guildcommand parameters.");
							}
							else
								player->sendCancel("You don't have rights to revoke an invite of someone in your guild.");
						}
						else if(text.substr(0, 8) == "!promote" || text.substr(0, 7) == "!demote" || text.substr(0, 15) == "!passleadership" || text.substr(0, 5) == "!kick")
						{
							if(player->getGuildLevel() == GUILDLEVEL_LEADER)
							{
								std::string param;
								uint32_t length = 0;
								if(text[2] == 'r')
									length = 11;
								else if(text[2] == 'e')
									length = 10;
								else if(text[2] == 'a')
									length = 18;
								else
									length = 8;
								if(text.length() < length)
								{
									player->sendCancel("Invalid guildcommand parameters.");
									return false;
								}
								else
									length -= 2;
								param = text.substr(length);
								trimString(param);
								Player* paramPlayer = g_game.getPlayerByName(param);
								if(paramPlayer)
								{
									if(paramPlayer->getGuildId())
									{
										if(IOGuild::getInstance()->guildExists(paramPlayer->getGuildId()))
										{
											if(player->getGuildId() == paramPlayer->getGuildId())
											{
												if(text[2] == 'r')
												{
													if(paramPlayer->getGuildLevel() == GUILDLEVEL_MEMBER)
													{
														if(paramPlayer->isPremium())
														{
															paramPlayer->setGuildLevel(GUILDLEVEL_VICE);
															sprintf(buffer, "%s has promoted %s to %s.", player->getName().c_str(), paramPlayer->getName().c_str(), paramPlayer->getGuildRank().c_str());
															guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
														}
														else
															player->sendCancel("A player with that name does not have a premium account.");
													}
													else
														player->sendCancel("You can only promote Members to Vice-Leaders.");
												}
												else if(text[2] == 'e')
												{
													if(paramPlayer->getGuildLevel() == GUILDLEVEL_VICE)
													{
														paramPlayer->setGuildLevel(GUILDLEVEL_MEMBER);
														sprintf(buffer, "%s has demoted %s to %s.", player->getName().c_str(), paramPlayer->getName().c_str(), paramPlayer->getGuildRank().c_str());
														guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
													}
													else
														player->sendCancel("You can only demote Vice-Leaders to Members.");
												}
												else if(text[2] == 'a')
												{
													if(paramPlayer->getGuildLevel() == GUILDLEVEL_VICE)
													{
														const uint32_t levelToFormGuild = g_config.getNumber(ConfigManager::LEVEL_TO_FORM_GUILD);
														if(paramPlayer->getLevel() >= levelToFormGuild)
														{
															paramPlayer->setGuildLevel(GUILDLEVEL_LEADER);
															player->setGuildLevel(GUILDLEVEL_VICE);
															IOGuild::getInstance()->updateOwnerId(paramPlayer->getGuildId(), paramPlayer->getGUID());
															sprintf(buffer, "%s has passed the guild leadership to %s.", player->getName().c_str(), paramPlayer->getName().c_str());
															guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
														}
														else
														{
															sprintf(buffer, "The new guild leader has to be at least Level %d.", levelToFormGuild);
															player->sendCancel(buffer);
														}
													}
													else
														player->sendCancel("A player with that name is not a Vice-Leader.");
												}
												else
												{
													if(player->getGuildLevel() > paramPlayer->getGuildLevel())
													{
														sprintf(buffer, "%s has been kicked from the guild by %s.", paramPlayer->getName().c_str(), player->getName().c_str());
														guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
														paramPlayer->resetGuildInformation();
													}
													else
														player->sendCancel("You may only kick players with a guild rank below your.");
												}
											}
											else
												player->sendCancel("You are not in the same guild as a player with that name.");
										}
										else
											player->sendCancel("Could not find the guild of a player with that name.");
									}
									else
										player->sendCancel("A player with that name is not in a guild.");
								}
								else if(IOLoginData::getInstance()->playerExists(param))
								{
									uint32_t guid;
									IOLoginData::getInstance()->getGuidByName(guid, param);
									if(IOGuild::getInstance()->hasGuild(guid))
									{
										if(player->getGuildId() == IOGuild::getInstance()->getGuildId(guid))
										{
											if(text[2] == 'r')
											{
												if(IOGuild::getInstance()->getGuildLevel(guid) == GUILDLEVEL_MEMBER)
												{
													if(IOLoginData::getInstance()->isPremium(guid))
													{
														IOGuild::getInstance()->setGuildLevel(guid, GUILDLEVEL_VICE);
														sprintf(buffer, "%s has promoted %s to %s.", player->getName().c_str(), param.c_str(), IOGuild::getInstance()->getRankName(IOGuild::getInstance()->getGuildLevel(guid), IOGuild::getInstance()->getGuildId(guid)).c_str());
														guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
													}
													else
														player->sendCancel("A player with that name does not have a premium account.");
												}
												else
													player->sendCancel("You can only promote Members to Vice-Leaders.");
											}
											else if(text[2] == 'e')
											{
												if(IOGuild::getInstance()->getGuildLevel(guid) == GUILDLEVEL_VICE)
												{
													IOGuild::getInstance()->setGuildLevel(guid, GUILDLEVEL_MEMBER);
													sprintf(buffer, "%s has demoted %s to %s.", player->getName().c_str(), param.c_str(), IOGuild::getInstance()->getRankName(IOGuild::getInstance()->getGuildLevel(guid), IOGuild::getInstance()->getGuildId(guid)).c_str());
													guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
												}
												else
													player->sendCancel("You can only demote Vice-Leaders to Members.");
											}
											else if(text[2] == 'a')
											{
												if(IOGuild::getInstance()->getGuildLevel(guid) == GUILDLEVEL_VICE)
												{
													const uint32_t levelToFormGuild = g_config.getNumber(ConfigManager::LEVEL_TO_FORM_GUILD);
													if(IOLoginData::getInstance()->getLevel(guid) >= levelToFormGuild)
													{
														IOGuild::getInstance()->setGuildLevel(guid, GUILDLEVEL_LEADER);
														player->setGuildLevel(GUILDLEVEL_VICE);
														sprintf(buffer, "%s has passed the guild leadership to %s.", player->getName().c_str(), param.c_str());
														guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
													}
													else
													{
														sprintf(buffer, "The new guild leader has to be at least Level %d.", levelToFormGuild);
														player->sendCancel(buffer);
													}
												}
												else
													player->sendCancel("A player with that name is not a Vice-Leader.");
											}
											else
											{
												sprintf(buffer, "%s has been kicked from the guild by %s.", param.c_str(), player->getName().c_str());
												guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
												IOLoginData::getInstance()->resetGuildInformation(guid);
											}
										}
									}
									else
										player->sendCancel("A player with that name is not in a guild");
								}
								else
									player->sendCancel("A player with that name does not exist.");
							}
							else
								player->sendCancel("You are not the leader of your guild.");
						}
						else if(text.substr(0, 5) == "!nick")
						{
							if(text.length() > 7)
							{
								std::string param = text.substr(6);
								boost::char_separator<char> sep(",");
								tokenizer cmdtokens(param, sep);
								tokenizer::iterator cmdit = cmdtokens.begin();
								std::string param1, param2;
								param1 = parseParams(cmdit, cmdtokens.end());
								param2 = parseParams(cmdit, cmdtokens.end());
								trimString(param1);
								trimString(param2);
								Player* paramPlayer = g_game.getPlayerByName(param1);
								if(paramPlayer)
								{
									if(paramPlayer->getGuildId())
									{
										if(param2.length() > 3)
										{
											if(param2.length() < 15)
											{
												if(isValidName(param2, false))
												{
													if(IOGuild::getInstance()->guildExists(paramPlayer->getGuildId()))
													{
														if(player->getGuildId() == paramPlayer->getGuildId())
														{
															if(paramPlayer->getGuildLevel() < player->getGuildLevel() || (player == paramPlayer && player->getGuildLevel() > GUILDLEVEL_MEMBER))
															{
																paramPlayer->setGuildNick(param2);
																if(player != paramPlayer)
																	sprintf(buffer, "%s has set the guildnick of %s to \"%s\".", player->getName().c_str(), paramPlayer->getName().c_str(), param2.c_str());
																else
																	sprintf(buffer, "%s has set %s guildnick to \"%s\".", player->getName().c_str(), (player->getSex() == PLAYERSEX_FEMALE ? "her" : "his"), param2.c_str());
																guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
															}
															else
																player->sendCancel("You may only change the guild nick of players that have a lower rank than you.");
														}
														else
															player->sendCancel("A player with that name is not in your guild.");
													}
													else
														player->sendCancel("A player with that name's guild could not be found.");
												}
												else
													player->sendCancel("That guildnick is not valid");
											}
											else
												player->sendCancel("That guildnick is too long, please select a shorter one.");
										}
										else
											player->sendCancel("That guildnick is too short, please select a longer one.");
									}
									else
										player->sendCancel("A player with that name is not in a guild.");
								}
								else if(IOLoginData::getInstance()->playerExists(param1))
								{
									uint32_t guid;
									IOLoginData::getInstance()->getGuidByName(guid, (std::string&)param1);
									if(IOGuild::getInstance()->hasGuild(guid))
									{
										if(param2.length() > 3)
										{
											if(param2.length() < 15)
											{
												if(isValidName(param2, false))
												{
													if(IOGuild::getInstance()->guildExists(guid))
													{
														if(player->getGuildId() == IOGuild::getInstance()->getGuildId(guid))
														{
															if(IOGuild::getInstance()->getGuildLevel(guid) < player->getGuildLevel())
															{
																IOGuild::getInstance()->setGuildNick(guid, param2);
																sprintf(buffer, "%s has set the guildnick of %s to \"%s\".", player->getName().c_str(), param1.c_str(), param2.c_str());
																guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
															}
															else
																player->sendCancel("You may only change the guild nick of players that have a lower rank than you.");
														}
														else
															player->sendCancel("A player with that name is not in your guild.");
													}
													else
														player->sendCancel("A player with that name's guild could not be found.");
												}
												else
													player->sendCancel("That guildnick is not valid");
											}
											else
												player->sendCancel("That guildnick is too long, please select a shorter one.");
										}
										else
											player->sendCancel("That guildnick is too short, please select a longer one.");
									}
									else
										player->sendCancel("A player with that name is not in any guild");
								}
								else
									player->sendCancel("A player with that name does not exist.");
							}
							else
								player->sendCancel("Invalid guildcommand parameters");
						}
						else if(text.substr(0, 12) == "!setrankname")
						{
							if(text.length() > 14)
							{
								std::string param = text.substr(13);
								boost::char_separator<char> sep(",");
								tokenizer cmdtokens(param, sep);
								tokenizer::iterator cmdit = cmdtokens.begin();
								std::string param1, param2;
								param1 = parseParams(cmdit, cmdtokens.end());
								param2 = parseParams(cmdit, cmdtokens.end());
								trimString(param1);
								trimString(param2);
								if(player->getGuildLevel() == GUILDLEVEL_LEADER)
								{
									if(param2.length() > 3)
									{
										if(param2.length() < 21)
										{
											if(isValidName(param2, false))
											{
												if(IOGuild::getInstance()->rankNameExists(param1, player->getGuildId()))
												{
													if(!IOGuild::getInstance()->rankNameExists(param2, player->getGuildId()))
													{
														IOGuild::getInstance()->changeRankName(param1, param2, player->getGuildId());
														sprintf(buffer, "%s has renamed the guildrank: \"%s\", to: \"%s\".", player->getName().c_str(), param1.c_str(), param2.c_str());
														guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
													}
													else
														player->sendCancel("There is already a rank in your guild with that name");
												}
												else
													player->sendCancel("There is no such rankname in your guild");
											}
											else
												player->sendCancel("The new guildrank contains invalid characters");
										}
										else
											player->sendCancel("The new rankname is too long.");
									}
									else
										player->sendCancel("The new rankname is too short.");
								}
								else
									player->sendCancel("You are not the leader of your guild.");
							}
							else
								player->sendCancel("Invalid guildcommand parameters");
						}
						else if(text.substr(0, 8) == "!setmotd")
						{
							if(player->getGuildLevel() == GUILDLEVEL_LEADER)
							{
								if(text.length() > 9)
								{
									std::string param = text.substr(9);
									trimString(param);
									if(param.length() > 3)
									{
										if(param.length() < 225)
										{
											IOGuild::getInstance()->setMotd(player->getGuildId(), param);
											sprintf(buffer, "%s has set the Message of the Day to: %s", player->getName().c_str(), param.c_str());
											guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
										}
										else
											player->sendCancel("That motd is too long.");
									}
									else
										player->sendCancel("That motd is too short.");
								}
								else
									player->sendCancel("Invalid guildcommand parameters");
							}
							else
								player->sendCancel("Only the leader of your guild can set the guild motd.");
						}
						else if(text == "!cleanmotd")
						{
							if(player->getGuildLevel() == GUILDLEVEL_LEADER)
							{
								IOGuild::getInstance()->setMotd(player->getGuildId(), "");
								sprintf(buffer, "%s has cleaned the Message of the Day.", player->getName().c_str());
								guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
							}
							else
								player->sendCancel("Only the leader of your guild can clean the guild motd.");
						}
						else if(text == "!commands")
							player->sendToChannel(player, SPEAK_CHANNEL_R2, "The guild commands are: <!disband>, <!invite playerName>, <!leave>, <!kick playerName>, <!revoke playerName>, <!demote playerName>, <!promote playerName>, <!passleadership playerName>, <!nick playerName, nick>, <!setrankname oldRankName, newRankName>, <!setmotd newMotd> and <!cleanmotd>.", 0x00);
					}
					else
						player->sendCancel("It seems like your guild does not exist anymore.");
				}
				else
					player->sendCancel("You are not in a guild.");
				return true;
			}
		}

		switch(player->getGuildLevel())
		{
			case 2:
				type = SPEAK_CHANNEL_O;
				break;
			case 3:
				type = SPEAK_CHANNEL_R1;
				break;
			default:
				break;
		}
	}

	return channel->talk(player, type, text);
}

std::string Chat::getChannelName(Player* player, uint16_t channelId)
{
	if(ChatChannel* channel = getChannel(player, channelId))
		return channel->getName();
	else
		return "";
}

ChannelList Chat::getChannelList(Player* player)
{
	ChannelList list;
	bool gotPrivate = false;

	// If has guild
	if(player->getGuildId() && player->getGuildName().length())
	{
		if(ChatChannel* channel = getChannel(player, 0x00))
			list.push_back(channel);
		else if((channel = createChannel(player, 0x00)))
			list.push_back(channel);
	}

	for(NormalChannelMap::iterator nit = m_normalChannels.begin(); nit != m_normalChannels.end(); ++nit)
	{
		switch(nit->first)
		{
			case 0x01:
				if(!player->hasCustomFlag(PlayerCustomFlag_CanSeeStaffChannel))
					continue;
				break;

			case 0x02:
				if(!player->hasCustomFlag(PlayerCustomFlag_CanSeeCounsellorChannel))
					continue;
				break;

			case 0x03:
				if(!player->hasFlag(PlayerFlag_CanAnswerRuleViolations))
					continue;
				break;

			case 0x05:
				if(!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) && player->getVocationId() == 0)
					continue;
				break;

			case 0x06:
				if(!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) && player->getVocationId() != 0)
					continue;
				break;
		}

		list.push_back(nit->second);
	}

	for(PrivateChannelMap::iterator pit = m_privateChannels.begin(); pit != m_privateChannels.end(); ++pit)
	{
		if(PrivateChatChannel* channel = pit->second)
		{
			if(channel->isInvited(player))
				list.push_back(channel);

			if(channel->getOwner() == player->getGUID())
				gotPrivate = true;
		}
	}

	if(!gotPrivate && player->isPremium())
		list.push_front(dummyPrivate);

	return list;
}

ChatChannel* Chat::getChannel(Player* player, uint16_t channelId)
{
	if(channelId == 0x00)
	{
		GuildChannelMap::iterator git = m_guildChannels.find(player->getGuildId());
		if(git != m_guildChannels.end())
			return git->second;

		return NULL;
	}

	NormalChannelMap::iterator nit = m_normalChannels.find(channelId);
	if(nit != m_normalChannels.end())
	{
		switch(channelId)
		{
			case 0x01:
				if(!player->hasCustomFlag(PlayerCustomFlag_CanSeeStaffChannel))
					return NULL;
				break;

			case 0x02:
				if(!player->hasCustomFlag(PlayerCustomFlag_CanSeeCounsellorChannel))
					return NULL;
				break;

			case 0x03:
				if(!player->hasFlag(PlayerFlag_CanAnswerRuleViolations))
					return NULL;
				break;

			case 0x05:
				if(!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) && player->getVocationId() == 0)
					return NULL;
				break;

			case 0x06:
				if(!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) && player->getVocationId() != 0)
					return NULL;
				break;
		}
		return nit->second;
	}

	PrivateChannelMap::iterator pit = m_privateChannels.find(channelId);
	if(pit != m_privateChannels.end())
		return pit->second;

	return NULL;
}

ChatChannel* Chat::getChannelById(uint16_t channelId)
{
	NormalChannelMap::iterator it = m_normalChannels.find(channelId);
	if(it != m_normalChannels.end())
		return it->second;

	return NULL;
}

PrivateChatChannel* Chat::getPrivateChannel(Player* player)
{
	for(PrivateChannelMap::iterator it = m_privateChannels.begin(); it != m_privateChannels.end(); ++it)
	{
		if(PrivateChatChannel* channel = it->second)
		{
			if(channel->getOwner() == player->getGUID())
				return channel;
		}
	}
	return NULL;
}

in player.h what do you mean "in the public: (i put mine after the ghost stuff) add "
 
Last edited:
Monsters.cpp
Code:
//////////////////////////////////////////////////////////////////////
// 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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//////////////////////////////////////////////////////////////////////
#include "otpch.h"

#include "monsters.h"
#include "monster.h"
#include "container.h"
#include "tools.h"
#include "spells.h"
#include "combat.h"
#include "luascript.h"
#include "weapons.h"
#include "configmanager.h"

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

extern Spells* g_spells;
extern Monsters g_monsters;
extern ConfigManager g_config;

MonsterType::MonsterType()
{
	reset();
}

void MonsterType::reset()
{
	experience = 0;

	defense = 0;
	armor = 0;

	canPushItems = false;
	canPushCreatures = false;
	staticAttackChance = 95;
	maxSummons = 0;
	targetDistance = 1;
	runAwayHealth = 0;
	pushable = true;
	base_speed = 200;
	health = 100;
	health_max = 100;

	outfit.lookHead = 0;
	outfit.lookBody = 0;
	outfit.lookLegs = 0;
	outfit.lookFeet = 0;
	outfit.lookType = 0;
	outfit.lookTypeEx = 0;
	outfit.lookAddons = 0;
	lookcorpse = 0;

	conditionImmunities = 0;
	damageImmunities = 0;
	race = RACE_BLOOD;
	isSummonable = false;
	isIllusionable = false;
	isConvinceable = false;
	isAttackable = true;
	isHostile = true;

	lightLevel = 0;
	lightColor = 0;
	skull = SKULL_NONE;
	partyShield = SHIELD_NONE;

	manaCost = 0;
	summonList.clear();
	lootItems.clear();
	elementMap.clear();

	for(SpellList::iterator it = spellAttackList.begin(); it != spellAttackList.end(); ++it)
	{
		if(it->combatSpell)
		{
			delete it->spell;
			it->spell = NULL;
		}
	}

	spellAttackList.clear();

	for(SpellList::iterator it = spellDefenseList.begin(); it != spellDefenseList.end(); ++it)
	{
		if(it->combatSpell)
		{
			delete it->spell;
			it->spell = NULL;
		}
	}

	spellDefenseList.clear();

	yellSpeedTicks = 0;
	yellChance = 0;
	voiceVector.clear();

	changeTargetSpeed = 0;
	changeTargetChance = 0;

	scriptList.clear();
}

MonsterType::~MonsterType()
{
	reset();
}

uint32_t Monsters::getLootRandom()
{
	return random_range(0, MAX_LOOTCHANCE) / g_config.getNumber(ConfigManager::RATE_LOOT);
}

void MonsterType::createLoot(Container* corpse)
{
	for(LootItems::const_iterator it = lootItems.begin(); it != lootItems.end() && (corpse->capacity() - corpse->size() > 0); it++)
	{
		Item* tmpItem = createLootItem(*it);
		if(tmpItem)
		{
			//check containers
			if(Container* container = tmpItem->getContainer())
			{
				if(createLootContainer(container, *it))
					corpse->__internalAddThing(tmpItem);
				else
					delete container;
			}
			else
				corpse->__internalAddThing(tmpItem);
		}
	}
	corpse->__startDecaying();
}

Item* MonsterType::createLootItem(const LootBlock& lootBlock)
{
	Item* tmpItem = NULL;
	if(Item::items[lootBlock.id].stackable)
	{
		uint32_t randvalue = Monsters::getLootRandom();
		if(randvalue < lootBlock.chance)
		{
			uint32_t n = randvalue % lootBlock.countmax + 1;
			tmpItem = Item::CreateItem(lootBlock.id, n);
		}
	}
	else
	{
		if(Monsters::getLootRandom() < lootBlock.chance)
			tmpItem = Item::CreateItem(lootBlock.id, 0);
	}

	if(tmpItem)
	{
		if(lootBlock.subType != -1)
			tmpItem->setSubType(lootBlock.subType);

		if(lootBlock.actionId != -1)
			tmpItem->setActionId(lootBlock.actionId);

		if(lootBlock.uniqueId != -1)
			tmpItem->setUniqueId(lootBlock.uniqueId);

		if(lootBlock.text != "")
			tmpItem->setText(lootBlock.text);

		return tmpItem;
	}

	return NULL;
}

bool MonsterType::createLootContainer(Container* parent, const LootBlock& lootblock)
{
	if(parent->size() < parent->capacity())
	{
		LootItems::const_iterator it;
		if(it == lootblock.childLoot.end())
			return true;

		for(it = lootblock.childLoot.begin(); it != lootblock.childLoot.end(); it++)
		{
			Item* tmpItem = createLootItem(*it);
			if(tmpItem)
			{
				if(Container* container = tmpItem->getContainer())
				{
					if(createLootContainer(container, *it))
						parent->__internalAddThing(container);
					else
						delete container;
				}
				else
					parent->__internalAddThing(tmpItem);
			}
		}
	}

	if(parent->size() == 0)
		return false;

	return true;
}

Monsters::Monsters()
{
	loaded = false;
}

bool Monsters::loadFromXml(bool reloading /*= false*/)
{
	loaded = false;
	std::string filename = getFilePath(FILE_TYPE_OTHER, "monster/monsters.xml");

	xmlDocPtr doc = xmlParseFile(filename.c_str());
	if(doc)
	{
		loaded = true;
		xmlNodePtr root, p;
		root = xmlDocGetRootElement(doc);

		if(xmlStrcmp(root->name,(const xmlChar*)"monsters") != 0)
		{
			xmlFreeDoc(doc);
			loaded = false;
			return false;
		}

		p = root->children;
		while(p)
		{
			if(p->type != XML_ELEMENT_NODE)
			{
				p = p->next;
				continue;
			}

			if(xmlStrcmp(p->name, (const xmlChar*)"monster") == 0)
			{
				std::string file;
				std::string name;

				if(readXMLString(p, "file", file) && readXMLString(p, "name", name))
				{
					file = getFilePath(FILE_TYPE_OTHER, "monster/" + file);
					loadMonster(file, name, reloading);
				}
			}
			else
				std::cout << "[Warning - Monsters::loadFromXml]. Unknown node name. " << p->name << std::endl;

			p = p->next;
		}
		xmlFreeDoc(doc);
	}
	return loaded;
}

bool Monsters::reload()
{
	return loadFromXml(true);
}

ConditionDamage* Monsters::getDamageCondition(ConditionType_t conditionType,
	int32_t maxDamage, int32_t minDamage, int32_t startDamage, uint32_t tickInterval)
{
	ConditionDamage* condition = dynamic_cast<ConditionDamage*>(Condition::createCondition(CONDITIONID_COMBAT, conditionType, 0, 0));
	condition->setParam(CONDITIONPARAM_TICKINTERVAL, tickInterval);
	condition->setParam(CONDITIONPARAM_MINVALUE, minDamage);
	condition->setParam(CONDITIONPARAM_MAXVALUE, maxDamage);
	condition->setParam(CONDITIONPARAM_STARTVALUE, startDamage);
	condition->setParam(CONDITIONPARAM_DELAYED, 1);
	return condition;
}

bool Monsters::deserializeSpell(xmlNodePtr node, spellBlock_t& sb, const std::string& description)
{
	sb.chance = 100;
	sb.speed = 2000;
	sb.range = 0;
	sb.minCombatValue = 0;
	sb.maxCombatValue = 0;
	sb.combatSpell = false;
	sb.isMelee = false;

	std::string name = "", scriptName = "";
	bool isScripted = false;

	if(readXMLString(node, "script", scriptName))
		isScripted = true;
	else if(!readXMLString(node, "name", name))
		return false;

	int32_t intValue;
	std::string strValue;
	if(readXMLInteger(node, "speed", intValue) || readXMLInteger(node, "interval", intValue))
		sb.speed = std::max(1, intValue);

	if(readXMLInteger(node, "chance", intValue))
	{
		if(intValue < 0 || intValue > 100)
			intValue = 100;

		sb.chance = intValue;
	}

	if(readXMLInteger(node, "range", intValue))
	{
		if(intValue < 0 )
			intValue = 0;

		if(intValue > Map::maxViewportX * 2)
			intValue = Map::maxViewportX * 2;

		sb.range = intValue;
	}

	if(readXMLInteger(node, "min", intValue))
		sb.minCombatValue = intValue;

	if(readXMLInteger(node, "max", intValue))
	{
		sb.maxCombatValue = intValue;

		//normalize values
		if(std::abs(sb.minCombatValue) > std::abs(sb.maxCombatValue))
		{
			int32_t value = sb.maxCombatValue;
			sb.maxCombatValue = sb.minCombatValue;
			sb.minCombatValue = value;
		}
	}

	if((sb.spell = g_spells->getSpellByName(name)))
		return true;

	CombatSpell* combatSpell = NULL;
	bool needTarget = false;
	bool needDirection = false;

	if(isScripted)
	{
		if(readXMLInteger(node, "direction", intValue))
			needDirection = (intValue == 1);

		if(readXMLInteger(node, "target", intValue))
			needTarget = (intValue != 0);

		combatSpell = new CombatSpell(NULL, needTarget, needDirection);

		if(!combatSpell->loadScript(getFilePath(FILE_TYPE_OTHER, g_spells->getScriptBaseName() + "/scripts/" + scriptName)))
		{
			delete combatSpell;
			return false;
		}

		if(!combatSpell->loadScriptCombat())
		{
			delete combatSpell;
			return false;

		}

		combatSpell->getCombat()->setPlayerCombatValues(FORMULA_VALUE, sb.minCombatValue, 0, sb.maxCombatValue, 0);
	}
	else
	{
		Combat* combat = new Combat;
		sb.combatSpell = true;

		if(readXMLInteger(node, "length", intValue))
		{
			int32_t length = intValue;
			if(length > 0)
			{
				int32_t spread = 3;

				//need direction spell
				if(readXMLInteger(node, "spread", intValue))
					spread = std::max(0, intValue);

				AreaCombat* area = new AreaCombat();
				area->setupArea(length, spread);
				combat->setArea(area);

				needDirection = true;
			}
		}

		if(readXMLInteger(node, "radius", intValue))
		{
			int32_t radius = intValue;

			//target spell
			if(readXMLInteger(node, "target", intValue))
				needTarget = (intValue != 0);

			AreaCombat* area = new AreaCombat();
			area->setupArea(radius);
			combat->setArea(area);
		}

		std::string tmpName = asLowerCaseString(name);
		if(tmpName == "melee")
		{
			int32_t attack = 0;
			int32_t skill = 0;
			sb.isMelee = true;
			if(readXMLInteger(node, "attack", attack))
			{
				if(readXMLInteger(node, "skill", skill))
				{
					sb.minCombatValue = 0;
					sb.maxCombatValue = -Weapons::getMaxMeleeDamage(skill, attack);
				}
			}

			ConditionType_t conditionType = CONDITION_NONE;
			int32_t minDamage = 0;
			int32_t maxDamage = 0;
			int32_t startDamage = 0;
			uint32_t tickInterval = 2000;

			if(readXMLInteger(node, "fire", intValue))
			{
				conditionType = CONDITION_FIRE;

				minDamage = intValue;
				maxDamage = intValue;
				tickInterval = 10000;
			}
			else if(readXMLInteger(node, "poison", intValue))
			{
				conditionType = CONDITION_POISON;

				minDamage = intValue;
				maxDamage = intValue;
				tickInterval = 5000;
			}
			else if(readXMLInteger(node, "energy", intValue))
			{
				conditionType = CONDITION_ENERGY;

				minDamage = intValue;
				maxDamage = intValue;
				tickInterval = 10000;
			}
			else if(readXMLInteger(node, "drown", intValue))
			{
				conditionType = CONDITION_DROWN;

				minDamage = intValue;
				maxDamage = intValue;
				tickInterval = 10000;
			}
			else if(readXMLInteger(node, "freeze", intValue))
			{
				conditionType = CONDITION_FREEZING;

				minDamage = intValue;
				maxDamage = intValue;
				tickInterval = 10000;
			}
			else if(readXMLInteger(node, "dazzle", intValue))
			{
				conditionType = CONDITION_DAZZLED;

				minDamage = intValue;
				maxDamage = intValue;
				tickInterval = 10000;
			}
			else if(readXMLInteger(node, "curse", intValue))
			{
				conditionType = CONDITION_CURSED;

				minDamage = intValue;
				maxDamage = intValue;
				tickInterval = 10000;
			}

			if(readXMLInteger(node, "tick", intValue) && intValue > 0)
				tickInterval = intValue;

			if(conditionType != CONDITION_NONE)
			{
				Condition* condition = getDamageCondition(conditionType, maxDamage, minDamage, startDamage, tickInterval);
				combat->setCondition(condition);
			}

			sb.range = 1;
			combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_PHYSICALDAMAGE);
			combat->setParam(COMBATPARAM_BLOCKEDBYARMOR, 1);
			combat->setParam(COMBATPARAM_BLOCKEDBYSHIELD, 1);
		}
		else if(tmpName == "physical")
		{
			combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_PHYSICALDAMAGE);
			combat->setParam(COMBATPARAM_BLOCKEDBYARMOR, 1);
		}
		else if(tmpName == "poison" || tmpName == "earth")
			combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_EARTHDAMAGE);
		else if(tmpName == "fire")
			combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_FIREDAMAGE);
		else if(tmpName == "energy")
			combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_ENERGYDAMAGE);
		else if(tmpName == "drown")
			combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_DROWNDAMAGE);
		else if(tmpName == "ice")
			combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_ICEDAMAGE);
		else if(tmpName == "holy")
			combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_HOLYDAMAGE);
		else if(tmpName == "death")
			combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_DEATHDAMAGE);
		else if(tmpName == "lifedrain")
			combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_LIFEDRAIN);
		else if(tmpName == "manadrain")
			combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_MANADRAIN);
		else if(tmpName == "healing")
		{
			combat->setParam(COMBATPARAM_COMBATTYPE, COMBAT_HEALING);
			combat->setParam(COMBATPARAM_AGGRESSIVE, 0);
		}
		else if(tmpName == "speed")
		{
			int32_t speedChange = 0;
			int32_t duration = 10000;

			if(readXMLInteger(node, "duration", intValue))
				duration = intValue;

			if(readXMLInteger(node, "speedchange", intValue))
			{
				speedChange = intValue;
				if(speedChange < -1000)
				{
					//cant be slower than 100%
					speedChange = -1000;
				}
			}

			ConditionType_t conditionType;
			if(speedChange > 0)
			{
				conditionType = CONDITION_HASTE;
				combat->setParam(COMBATPARAM_AGGRESSIVE, 0);
			}
			else
				conditionType = CONDITION_PARALYZE;

			ConditionSpeed* condition = dynamic_cast<ConditionSpeed*>(Condition::createCondition(CONDITIONID_COMBAT, conditionType, duration, 0));
			condition->setFormulaVars(speedChange / 1000.0, 0, speedChange / 1000.0, 0);
			combat->setCondition(condition);
		}
		else if(tmpName == "outfit")
		{
			int32_t duration = 10000;

			if(readXMLInteger(node, "duration", intValue))
				duration = intValue;

			if(readXMLString(node, "monster", strValue))
			{
				MonsterType* mType = g_monsters.getMonsterType(strValue);
				if(mType)
				{
					ConditionOutfit* condition = dynamic_cast<ConditionOutfit*>(Condition::createCondition(CONDITIONID_COMBAT, CONDITION_OUTFIT, duration, 0));
					condition->addOutfit(mType->outfit);
					combat->setParam(COMBATPARAM_AGGRESSIVE, 0);
					combat->setCondition(condition);
				}
			}
			else if(readXMLInteger(node, "item", intValue))
			{
				Outfit_t outfit;
				outfit.lookTypeEx = intValue;

				ConditionOutfit* condition = dynamic_cast<ConditionOutfit*>(Condition::createCondition(CONDITIONID_COMBAT, CONDITION_OUTFIT, duration, 0));
				condition->addOutfit(outfit);
				combat->setParam(COMBATPARAM_AGGRESSIVE, 0);
				combat->setCondition(condition);
			}
		}
		else if(tmpName == "invisible")
		{
			int32_t duration = 10000;

			if(readXMLInteger(node, "duration", intValue))
				duration = intValue;

			Condition* condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_INVISIBLE, duration, 0);
			combat->setParam(COMBATPARAM_AGGRESSIVE, 0);
			combat->setCondition(condition);
		}
		else if(tmpName == "drunk")
		{
			int32_t duration = 10000;

			if(readXMLInteger(node, "duration", intValue))
				duration = intValue;

			Condition* condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_DRUNK, duration, 0);
			combat->setCondition(condition);
		}
		else if(tmpName == "firefield")
			combat->setParam(COMBATPARAM_CREATEITEM, 1492);
		else if(tmpName == "poisonfield")
			combat->setParam(COMBATPARAM_CREATEITEM, 1496);
		else if(tmpName == "energyfield")
			combat->setParam(COMBATPARAM_CREATEITEM, 1495);
		else if(tmpName == "firecondition" ||
				tmpName == "poisoncondition" ||
				tmpName == "energycondition" ||
				tmpName == "drowncondition")
		{
			ConditionType_t conditionType = CONDITION_NONE;
			uint32_t tickInterval = 2000;

			if(tmpName == "firecondition")
			{
				conditionType = CONDITION_FIRE;
				tickInterval = 10000;
			}
			else if(tmpName == "poisoncondition")
			{
				conditionType = CONDITION_POISON;
				tickInterval = 5000;
			}
			else if(tmpName == "energycondition")
			{
				conditionType = CONDITION_ENERGY;
				tickInterval = 10000;
			}
			else if(tmpName == "drowncondition")
			{
				conditionType = CONDITION_DROWN;
				tickInterval = 5000;
			}
			else if(tmpName == "freezecondition")
			{
				conditionType = CONDITION_FREEZING;
				tickInterval = 10000;
			}
			else if(tmpName == "cursecondition")
			{
				conditionType = CONDITION_CURSED;
				tickInterval = 10000;
			}

			if(readXMLInteger(node, "tick", intValue) && intValue > 0)
				tickInterval = intValue;

			int32_t minDamage = std::abs(sb.minCombatValue);
			int32_t maxDamage = std::abs(sb.maxCombatValue);
			int32_t startDamage = 0;

			if(readXMLInteger(node, "start", intValue))
			{
				intValue = std::abs(intValue);
				if(intValue <= minDamage)
					startDamage = intValue;
			}

			Condition* condition = getDamageCondition(conditionType, maxDamage, minDamage, startDamage, tickInterval);
			combat->setCondition(condition);
		}
		else if(tmpName == "strength")
		{
			//
		}
		else
		{
			std::cout << "Error: [Monsters::deserializeSpell] - " << description <<  " - Unknown spell name: " << name << std::endl;
			delete combat;
			return false;
		}

		combat->setPlayerCombatValues(FORMULA_VALUE, sb.minCombatValue, 0, sb.maxCombatValue, 0);
		combatSpell = new CombatSpell(combat, needTarget, needDirection);

		xmlNodePtr attributeNode = node->children;

		while(attributeNode)
		{
			if(xmlStrcmp(attributeNode->name, (const xmlChar*)"attribute") == 0)
			{
				if(readXMLString(attributeNode, "key", strValue))
				{
					std::string tmpStrValue = asLowerCaseString(strValue);
					if(tmpStrValue == "shooteffect")
					{
						if(readXMLString(attributeNode, "value", strValue))
						{
							ShootType_t shoot = getShootType(strValue);
							if(shoot != NM_SHOOT_UNK)
								combat->setParam(COMBATPARAM_DISTANCEEFFECT, shoot);
							else
								std::cout << "Warning: [Monsters::deserializeSpell] - "  << description << " - Unknown shootEffect: " << strValue << std::endl;
						}
					}
					else if(tmpStrValue == "areaeffect")
					{
						if(readXMLString(attributeNode, "value", strValue))
						{
							MagicEffectClasses effect = getMagicEffect(strValue);
							if(effect != NM_ME_UNK)
								combat->setParam(COMBATPARAM_EFFECT, effect);
							else
								std::cout << "Warning: [Monsters::deserializeSpell] - "  << description << " - Unknown areaEffect: " << strValue << std::endl;
						}
					}
					else
						std::cout << "[Warning - Monsters::deserializeSpells] Effect type \"" << strValue << "\" does not exist." << std::endl;
				}
			}
			attributeNode = attributeNode->next;
		}
	}

	sb.spell = combatSpell;
	return true;
}

#define SHOW_XML_WARNING(desc) std::cout << "[Warning - Monsters::loadMonster] " << desc << ". " << file << std::endl;
#define SHOW_XML_ERROR(desc) std::cout << "[Error - Monsters::loadMonster] " << desc << ". " << file << std::endl;

bool Monsters::loadMonster(const std::string& file, const std::string& monster_name, bool reloading /*= false*/)
{
	bool monsterLoad;
	MonsterType* mType = NULL;
	bool new_mType = true;

	if(reloading)
	{
		uint32_t id = getIdByName(monster_name);
		if(id != 0)
		{
			mType = getMonsterType(id);
			if(mType != NULL)
			{
				new_mType = false;
				mType->reset();
			}
		}
	}
	if(new_mType)
		mType = new MonsterType();

	monsterLoad = true;
	xmlDocPtr doc = xmlParseFile(file.c_str());

	if(doc)
	{
		xmlNodePtr root, p;
		root = xmlDocGetRootElement(doc);

		if(xmlStrcmp(root->name,(const xmlChar*)"monster") != 0)
			std::cerr << "Malformed XML: " << file << std::endl;

		int32_t intValue;
		std::string strValue;

		p = root->children;

		if(readXMLString(root, "name", strValue))
			mType->name = strValue;
		else
			monsterLoad = false;

		if(readXMLString(root, "nameDescription", strValue))
			mType->nameDescription = strValue;
		else
		{
			mType->nameDescription = "a " + mType->name;
			toLowerCaseString(mType->nameDescription);
		}

		if(readXMLString(root, "race", strValue))
		{
			std::string tmpStrValue = asLowerCaseString(strValue);
			if(tmpStrValue == "venom" || atoi(strValue.c_str()) == 1)
				mType->race = RACE_VENOM;
			else if(tmpStrValue == "blood" || atoi(strValue.c_str()) == 2)
				mType->race = RACE_BLOOD;
			else if(tmpStrValue == "undead" || atoi(strValue.c_str()) == 3)
				mType->race = RACE_UNDEAD;
			else if(tmpStrValue == "fire" || atoi(strValue.c_str()) == 4)
				mType->race = RACE_FIRE;
			else
				SHOW_XML_WARNING("Unknown race type " << strValue);
		}

		if(readXMLInteger(root, "experience", intValue))
			mType->experience = intValue;

		if(readXMLInteger(root, "speed", intValue))
			mType->base_speed = intValue;

		if(readXMLInteger(root, "manacost", intValue))
			mType->manaCost = intValue;

		while(p)
		{
			if(p->type != XML_ELEMENT_NODE)
			{
				p = p->next;
				continue;
			}

			if(xmlStrcmp(p->name, (const xmlChar*)"health") == 0)
			{
				if(readXMLInteger(p, "now", intValue))
					mType->health = intValue;
				else
				{
					SHOW_XML_ERROR("Missing health.now");
					monsterLoad = false;
				}

				if(readXMLInteger(p, "max", intValue))
					mType->health_max = intValue;
				else
				{
					SHOW_XML_ERROR("Missing health.max");
					monsterLoad = false;
				}
			}
			else if(xmlStrcmp(p->name, (const xmlChar*)"flags") == 0)
			{
				xmlNodePtr tmpNode = p->children;
				while(tmpNode)
				{
					if(xmlStrcmp(tmpNode->name, (const xmlChar*)"flag") == 0)
					{
						if(readXMLInteger(tmpNode, "summonable", intValue))
							mType->isSummonable = (intValue != 0);

						if(readXMLInteger(tmpNode, "attackable", intValue))
							mType->isAttackable = (intValue != 0);

						if(readXMLInteger(tmpNode, "hostile", intValue))
							mType->isHostile = (intValue != 0);

						if(readXMLInteger(tmpNode, "illusionable", intValue))
							mType->isIllusionable = (intValue != 0);

						if(readXMLInteger(tmpNode, "convinceable", intValue))
							mType->isConvinceable = (intValue != 0);

						if(readXMLInteger(tmpNode, "pushable", intValue))
							mType->pushable = (intValue != 0);

						if(readXMLInteger(tmpNode, "canpushitems", intValue))
							mType->canPushItems = (intValue != 0);

						if(readXMLInteger(tmpNode, "canpushcreatures", intValue))
							mType->canPushCreatures = (intValue != 0);

						if(readXMLInteger(tmpNode, "staticattack", intValue))
						{
							if(intValue < 0)
							{
								SHOW_XML_WARNING("staticattack lower than 0");
								intValue = 0;
							}

							if(intValue > 100)
							{
								SHOW_XML_WARNING("staticattack greater than 100");
								intValue = 100;
							}
							mType->staticAttackChance = intValue;
						}

						if(readXMLInteger(tmpNode, "lightlevel", intValue))
							mType->lightLevel = intValue;

						if(readXMLInteger(tmpNode, "lightcolor", intValue))
							mType->lightColor = intValue;

						if(readXMLInteger(tmpNode, "targetdistance", intValue))
						{
							/*if(intValue > 6)
								SHOW_XML_WARNING("targetdistance greater than 6");*/

							mType->targetDistance = std::max(1, intValue);
						}

						if(readXMLInteger(tmpNode, "runonhealth", intValue))
							mType->runAwayHealth = intValue;

						if(readXMLString(tmpNode, "skull", strValue))
						{
							std::string tmpStrValue = asLowerCaseString(strValue);
							if(tmpStrValue == "red" || tmpStrValue == "4")
								mType->skull = SKULL_RED;
							else if(tmpStrValue == "white" || tmpStrValue == "3")
								mType->skull = SKULL_WHITE;
							else if(tmpStrValue == "green" || tmpStrValue == "2")
								mType->skull = SKULL_GREEN;
							else if(tmpStrValue == "yellow" || tmpStrValue == "1")
								mType->skull = SKULL_YELLOW;
							else
								mType->skull = SKULL_NONE;
						}

						if(readXMLString(tmpNode, "shield", strValue))
						{
							std::string tmpStrValue = asLowerCaseString(strValue);
							if(tmpStrValue == "whitenoshareoff" || tmpStrValue == "10")
								mType->partyShield = SHIELD_YELLOW_NOSHAREDEXP;
							else if(tmpStrValue == "blueshareoff" || tmpStrValue == "9")
								mType->partyShield = SHIELD_BLUE_NOSHAREDEXP;
							else if(tmpStrValue == "yellowshareblink" || tmpStrValue == "8")
								mType->partyShield = SHIELD_YELLOW_NOSHAREDEXP_BLINK;
							else if(tmpStrValue == "blueshareblink" || tmpStrValue == "7")
								mType->partyShield = SHIELD_BLUE_NOSHAREDEXP_BLINK;
							else if(tmpStrValue == "yellowshareon" || tmpStrValue == "6")
								mType->partyShield = SHIELD_YELLOW_SHAREDEXP;
							else if(tmpStrValue == "blueshareon" || tmpStrValue == "5")
								mType->partyShield = SHIELD_BLUE_SHAREDEXP;
							else if(tmpStrValue == "yellow" || tmpStrValue == "4")
								mType->partyShield = SHIELD_YELLOW;
							else if(tmpStrValue == "blue" || tmpStrValue == "3")
								mType->partyShield = SHIELD_BLUE;
							else if(tmpStrValue == "whiteyellow" || tmpStrValue == "2")
								mType->partyShield = SHIELD_WHITEYELLOW;
							else if(tmpStrValue == "whiteblue" || tmpStrValue == "1")
								mType->partyShield = SHIELD_WHITEBLUE;
							else
								mType->partyShield = SHIELD_NONE;
						}
					}
					tmpNode = tmpNode->next;
				}
				//if a monster can push creatures,
				// it should not be pushable
				if(mType->canPushCreatures && mType->pushable)
					mType->pushable = false;
			}
			else if(xmlStrcmp(p->name, (const xmlChar*)"targetchange") == 0)
			{
				if(readXMLInteger(p, "speed", intValue) || readXMLInteger(p, "interval", intValue))
					mType->changeTargetSpeed = std::max(1, intValue);
				else
					SHOW_XML_WARNING("Missing targetchange.speed");

				if(readXMLInteger(p, "chance", intValue))
					mType->changeTargetChance = intValue;
				else
					SHOW_XML_WARNING("Missing targetchange.chance");
			}
			else if(xmlStrcmp(p->name, (const xmlChar*)"strategy") == 0)
			{
				if(readXMLInteger(p, "attack", intValue)){}
					//mType->attackStrength = intValue;

				if(readXMLInteger(p, "defense", intValue)){}
					//mType->defenseStrength = intValue;
			}
			else if(xmlStrcmp(p->name, (const xmlChar*)"look") == 0)
			{
				if(readXMLInteger(p, "type", intValue))
				{
					mType->outfit.lookType = intValue;
					if(readXMLInteger(p, "head", intValue))
						mType->outfit.lookHead = intValue;

					if(readXMLInteger(p, "body", intValue))
						mType->outfit.lookBody = intValue;

					if(readXMLInteger(p, "legs", intValue))
						mType->outfit.lookLegs = intValue;

					if(readXMLInteger(p, "feet", intValue))
						mType->outfit.lookFeet = intValue;

					if(readXMLInteger(p, "addons", intValue))
						mType->outfit.lookAddons = intValue;
				}
				else if(readXMLInteger(p, "typeex", intValue))
					mType->outfit.lookTypeEx = intValue;
				else
					SHOW_XML_WARNING("Missing look type/typeex");

				if(readXMLInteger(p, "corpse", intValue))
					mType->lookcorpse = intValue;
			}
			else if(xmlStrcmp(p->name, (const xmlChar*)"attacks") == 0)
			{
				xmlNodePtr tmpNode = p->children;
				while(tmpNode)
				{
					if(xmlStrcmp(tmpNode->name, (const xmlChar*)"attack") == 0)
					{
						spellBlock_t sb;
						if(deserializeSpell(tmpNode, sb, monster_name))
							mType->spellAttackList.push_back(sb);
						else
							SHOW_XML_WARNING("Cant load spell");
					}
					tmpNode = tmpNode->next;
				}
			}
			else if(xmlStrcmp(p->name, (const xmlChar*)"defenses") == 0)
			{
				if(readXMLInteger(p, "defense", intValue))
					mType->defense = intValue;

				if(readXMLInteger(p, "armor", intValue))
					mType->armor = intValue;

				xmlNodePtr tmpNode = p->children;
				while(tmpNode)
				{
					if(xmlStrcmp(tmpNode->name, (const xmlChar*)"defense") == 0)
					{
						spellBlock_t sb;
						if(deserializeSpell(tmpNode, sb, monster_name))
							mType->spellDefenseList.push_back(sb);
						else
							SHOW_XML_WARNING("Cant load spell");
					}
					tmpNode = tmpNode->next;
				}
			}
			else if(xmlStrcmp(p->name, (const xmlChar*)"immunities") == 0)
			{
				xmlNodePtr tmpNode = p->children;
				while(tmpNode)
				{
					if(xmlStrcmp(tmpNode->name, (const xmlChar*)"immunity") == 0)
					{
						if(readXMLString(tmpNode, "name", strValue))
						{
							std::string tmpStrValue = asLowerCaseString(strValue);
							if(tmpStrValue == "physical")
							{
								mType->damageImmunities |= COMBAT_PHYSICALDAMAGE;
								//mType->conditionImmunities |= CONDITION_PHYSICAL;
							}
							else if(tmpStrValue == "energy")
							{
								mType->damageImmunities |= COMBAT_ENERGYDAMAGE;
								mType->conditionImmunities |= CONDITION_ENERGY;
							}
							else if(tmpStrValue == "fire")
							{
								mType->damageImmunities |= COMBAT_FIREDAMAGE;
								mType->conditionImmunities |= CONDITION_FIRE;
							}
							else if(tmpStrValue == "poison" ||
								tmpStrValue == "earth")
							{
								mType->damageImmunities |= COMBAT_EARTHDAMAGE;
								mType->conditionImmunities |= CONDITION_POISON;
							}
							else if(tmpStrValue == "drown")
							{
								mType->damageImmunities |= COMBAT_DROWNDAMAGE;
								mType->conditionImmunities |= CONDITION_DROWN;
							}
							else if(tmpStrValue == "ice")
							{
								mType->damageImmunities |= COMBAT_ICEDAMAGE;
								mType->conditionImmunities |= CONDITION_FREEZING;
							}
							else if(tmpStrValue == "holy")
							{
								mType->damageImmunities |= COMBAT_HOLYDAMAGE;
								mType->conditionImmunities |= CONDITION_DAZZLED;
							}
							else if(tmpStrValue == "death")
							{
								mType->damageImmunities |= COMBAT_DEATHDAMAGE;
								mType->conditionImmunities |= CONDITION_CURSED;
							}
							else if(tmpStrValue == "lifedrain")
							{
								mType->damageImmunities |= COMBAT_LIFEDRAIN;
								mType->conditionImmunities |= CONDITION_LIFEDRAIN;
							}
							else if(tmpStrValue == "paralyze")
								mType->conditionImmunities |= CONDITION_PARALYZE;
							else if(tmpStrValue == "outfit")
								mType->conditionImmunities |= CONDITION_OUTFIT;
							else if(tmpStrValue == "drunk")
								mType->conditionImmunities |= CONDITION_DRUNK;
							else if(tmpStrValue == "invisible")
								mType->conditionImmunities |= CONDITION_INVISIBLE;
							else
								SHOW_XML_WARNING("Unknown immunity name " << strValue);
						}
						//old immunities code
						else if(readXMLInteger(tmpNode, "physical", intValue))
						{
							if(intValue != 0)
							{
								mType->damageImmunities |= COMBAT_PHYSICALDAMAGE;
								//mType->conditionImmunities |= CONDITION_PHYSICAL;
							}
						}
						else if(readXMLInteger(tmpNode, "energy", intValue))
						{
							if(intValue != 0)
							{
								mType->damageImmunities |= COMBAT_ENERGYDAMAGE;
								mType->conditionImmunities |= CONDITION_ENERGY;
							}
						}
						else if(readXMLInteger(tmpNode, "fire", intValue))
						{
							if(intValue != 0)
							{
								mType->damageImmunities |= COMBAT_FIREDAMAGE;
								mType->conditionImmunities |= CONDITION_FIRE;
							}
						}
						else if(readXMLInteger(tmpNode, "poison", intValue) ||
							readXMLInteger(tmpNode, "earth", intValue))
						{
							if(intValue != 0)
							{
								mType->damageImmunities |= COMBAT_EARTHDAMAGE;
								mType->conditionImmunities |= CONDITION_POISON;
							}
						}
						else if(readXMLInteger(tmpNode, "drown", intValue))
						{
							if(intValue != 0)
							{
								mType->damageImmunities |= COMBAT_DROWNDAMAGE;
								mType->conditionImmunities |= CONDITION_DROWN;
							}
						}
						else if(readXMLInteger(tmpNode, "ice", intValue))
						{
							if(intValue != 0)
							{
								mType->damageImmunities |= COMBAT_ICEDAMAGE;
								mType->conditionImmunities |= CONDITION_FREEZING;
							}
						}
						else if(readXMLInteger(tmpNode, "holy", intValue))
						{
							if(intValue != 0)
							{
								mType->damageImmunities |= COMBAT_HOLYDAMAGE;
								mType->conditionImmunities |= CONDITION_DAZZLED;
							}
						}
						else if(readXMLInteger(tmpNode, "death", intValue))
						{
							if(intValue != 0)
							{
								mType->damageImmunities |= COMBAT_DEATHDAMAGE;
								mType->conditionImmunities |= CONDITION_CURSED;
							}
						}
						else if(readXMLInteger(tmpNode, "lifedrain", intValue))
						{
							if(intValue != 0)
							{
								mType->damageImmunities |= COMBAT_LIFEDRAIN;
								mType->conditionImmunities |= CONDITION_LIFEDRAIN;
							}
						}
						else if(readXMLInteger(tmpNode, "paralyze", intValue))
						{
							if(intValue != 0)
								mType->conditionImmunities |= CONDITION_PARALYZE;
						}
						else if(readXMLInteger(tmpNode, "outfit", intValue))
						{
							if(intValue != 0)
								mType->conditionImmunities |= CONDITION_OUTFIT;
						}
						else if(readXMLInteger(tmpNode, "drunk", intValue))
						{
							if(intValue != 0)
								mType->conditionImmunities |= CONDITION_DRUNK;
						}
						else if(readXMLInteger(tmpNode, "invisible", intValue))
						{
							if(intValue != 0)
								mType->conditionImmunities |= CONDITION_INVISIBLE;
						}
						else
							SHOW_XML_WARNING("Unknown immunity " << strValue);
					}
					tmpNode = tmpNode->next;
				}
			}
			else if(xmlStrcmp(p->name, (const xmlChar*)"voices") == 0)
			{
				xmlNodePtr tmpNode = p->children;
				if(readXMLInteger(p, "speed", intValue) || readXMLInteger(p, "interval", intValue))
					mType->yellSpeedTicks = intValue;
				else
					SHOW_XML_WARNING("Missing voices.speed");

				if(readXMLInteger(p, "chance", intValue))
					mType->yellChance = intValue;
				else
					SHOW_XML_WARNING("Missing voices.chance");

				while(tmpNode)
				{
					if(xmlStrcmp(tmpNode->name, (const xmlChar*)"voice") == 0)
					{
						voiceBlock_t vb;
						vb.text = "";
						vb.yellText = false;

						if(readXMLString(tmpNode, "sentence", strValue))
							vb.text = strValue;
						else
							SHOW_XML_WARNING("Missing voice.sentence");

						if(readXMLInteger(tmpNode, "yell", intValue))
							vb.yellText = (intValue != 0);

						mType->voiceVector.push_back(vb);
					}
					tmpNode = tmpNode->next;
				}
			}
			else if(xmlStrcmp(p->name, (const xmlChar*)"loot") == 0)
			{
				xmlNodePtr tmpNode = p->children;
				while(tmpNode)
				{
					if(tmpNode->type != XML_ELEMENT_NODE)
					{
						tmpNode = tmpNode->next;
						continue;
					}

					LootBlock lootBlock;
					if(loadLootItem(tmpNode, lootBlock))
						mType->lootItems.push_back(lootBlock);
					else
						SHOW_XML_WARNING("Cant load loot");

					tmpNode = tmpNode->next;
				}
			}
			else if(xmlStrcmp(p->name, (const xmlChar*)"elements") == 0)
			{
				xmlNodePtr tmpNode = p->children;
				while(tmpNode)
				{
					if(xmlStrcmp(tmpNode->name, (const xmlChar*)"element") == 0)
					{
						if(readXMLInteger(tmpNode, "physicalPercent", intValue))
							mType->elementMap[COMBAT_PHYSICALDAMAGE] = intValue;
						else if(readXMLInteger(tmpNode, "icePercent", intValue))
							mType->elementMap[COMBAT_ICEDAMAGE] = intValue;
						else if(readXMLInteger(tmpNode, "poisonPercent", intValue) ||
							readXMLInteger(tmpNode, "earthPercent", intValue))
							mType->elementMap[COMBAT_EARTHDAMAGE] = intValue;
						else if(readXMLInteger(tmpNode, "firePercent", intValue))
							mType->elementMap[COMBAT_FIREDAMAGE] = intValue;
						else if(readXMLInteger(tmpNode, "energyPercent", intValue))
							mType->elementMap[COMBAT_ENERGYDAMAGE] = intValue;
						else if(readXMLInteger(tmpNode, "holyPercent", intValue))
							mType->elementMap[COMBAT_HOLYDAMAGE] = intValue;
						else if(readXMLInteger(tmpNode, "deathPercent", intValue))
							mType->elementMap[COMBAT_DEATHDAMAGE] = intValue;
					}
					tmpNode = tmpNode->next;
				}
			}
			else if(xmlStrcmp(p->name, (const xmlChar*)"summons") == 0)
			{
				if(readXMLInteger(p, "maxSummons", intValue))
					mType->maxSummons = std::min(intValue, 100);
				else
					SHOW_XML_WARNING("Missing summons.maxSummons");

				xmlNodePtr tmpNode = p->children;
				while(tmpNode)
				{
					if(xmlStrcmp(tmpNode->name, (const xmlChar*)"summon") == 0)
					{
						uint32_t chance = 100;
						uint32_t interval = 1000;
						uint32_t amount = 1;

						if(readXMLInteger(tmpNode, "speed", intValue) || readXMLInteger(tmpNode, "interval", intValue))
							interval = intValue;

						if(readXMLInteger(tmpNode, "chance", intValue))
							chance = intValue;

						if(readXMLInteger(tmpNode, "amount", intValue) || readXMLInteger(tmpNode, "max", intValue))
							amount = intValue;

						if(readXMLString(tmpNode, "name", strValue))
						{
							summonBlock_t sb;
							sb.name = strValue;
							sb.interval = interval;
							sb.chance = chance;
							sb.amount = amount;

							mType->summonList.push_back(sb);
						}
						else
							SHOW_XML_WARNING("Missing summon.name");
					}
					tmpNode = tmpNode->next;
				}
			}
			else if(xmlStrcmp(p->name, (const xmlChar*)"script") == 0)
			{
				xmlNodePtr tmpNode = p->children;
				while(tmpNode)
				{
					if(xmlStrcmp(tmpNode->name, (const xmlChar*)"event") == 0)
					{
						if(readXMLString(tmpNode, "name", strValue))
							mType->scriptList.push_back(strValue);
						else
							SHOW_XML_WARNING("Missing name for script event");
					}
					tmpNode = tmpNode->next;
				}
			}
			else
				SHOW_XML_WARNING("Unknown attribute type - " << p->name);

			p = p->next;
		}
		xmlFreeDoc(doc);
	}
	else
		monsterLoad = false;

	if(monsterLoad)
	{
		static uint32_t id = 0;
		if(new_mType)
		{
			std::string lowername = monster_name;
			toLowerCaseString(lowername);

			id++;
			monsterNames[lowername] = id;
			monsters[id] = mType;
		}
		return true;
	}
	else
	{
		if(new_mType)
			delete mType;

		return false;
	}
}

bool Monsters::loadLootItem(xmlNodePtr node, LootBlock& lootBlock)
{
	int32_t intValue;
	std::string strValue;

	if(readXMLInteger(node, "id", intValue))
		lootBlock.id = intValue;

	if(lootBlock.id == 0)
		return false;

	if(readXMLInteger(node, "countmax", intValue))
	{
		lootBlock.countmax = intValue;
		if(lootBlock.countmax > 100)
			lootBlock.countmax = 100;
	}
	else
		lootBlock.countmax = 1;

	if(readXMLInteger(node, "chance", intValue) || readXMLInteger(node, "chance1", intValue))
	{
		lootBlock.chance = intValue;
		if(lootBlock.chance > MAX_LOOTCHANCE)
			lootBlock.chance = MAX_LOOTCHANCE;
	}
	else
		lootBlock.chance = MAX_LOOTCHANCE;

	if(Item::items[lootBlock.id].isContainer())
		loadLootContainer(node, lootBlock);

	//optional
	if(readXMLInteger(node, "subtype", intValue))
		lootBlock.subType = intValue;

	if(readXMLInteger(node, "actionId", intValue))
		lootBlock.actionId = intValue;

	if(readXMLInteger(node, "uniqueId", intValue))
		lootBlock.uniqueId = intValue;

	if(readXMLString(node, "text", strValue))
		lootBlock.text = strValue;

	return true;
}

bool Monsters::loadLootContainer(xmlNodePtr node, LootBlock& lBlock)
{
	if(node == NULL)
		return false;

	xmlNodePtr tmpNode = node->children;
	xmlNodePtr p;

	if(tmpNode == NULL)
		return false;

	while(tmpNode)
	{
		if(xmlStrcmp(tmpNode->name, (const xmlChar*)"inside") == 0)
		{
			p = tmpNode->children;
			while(p)
			{
				LootBlock lootBlock;
				if(loadLootItem(p, lootBlock))
					lBlock.childLoot.push_back(lootBlock);
				p = p->next;
			}
			return true;
		}
		tmpNode = tmpNode->next;
	}
	return false;
}

MonsterType* Monsters::getMonsterType(const std::string& name)
{
	uint32_t mId = getIdByName(name);
	if(mId == 0)
		return NULL;

	return getMonsterType(mId);
}

MonsterType* Monsters::getMonsterType(uint32_t mid)
{
	MonsterMap::iterator it = monsters.find(mid);
	if(it != monsters.end())
		return it->second;
	else
		return NULL;
}

uint32_t Monsters::getIdByName(const std::string& name)
{
	std::string lower_name = name;
	std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), tolower);
	MonsterNameMap::iterator it = monsterNames.find(lower_name);
	if(it != monsterNames.end())
		return it->second;
	else
		return 0;
}

Monsters::~Monsters()
{
	for(MonsterMap::iterator it = monsters.begin(); it != monsters.end(); it++)
		delete it->second;
}
 
newest 0.3 rev of the tfs server... Not there.. neither the channel nor that code.. any other ideas?

Here is the Enums.h i have for the tfs...

Code:
//////////////////////////////////////////////////////////////////////
// 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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//////////////////////////////////////////////////////////////////////

#ifndef __OTSERV_ENUMS_H__
#define __OTSERV_ENUMS_H__
#include <string>
#include <list>

enum DatabaseEngine_t
{
	DATABASE_ENGINE_NONE = 0,
	DATABASE_ENGINE_MYSQL = 1,
	DATABASE_ENGINE_SQLITE = 2,
	DATABASE_ENGINE_POSTGRESQL = 3,
	DATABASE_ENGINE_ODBC = 4
};

enum PasswordType_t
{
	PASSWORD_TYPE_PLAIN = 0,
	PASSWORD_TYPE_MD5 = 1,
	PASSWORD_TYPE_SHA1 = 2
};

enum GuildLevel_t
{
	GUILDLEVEL_MEMBER = 1,
	GUILDLEVEL_VICE = 2,
	GUILDLEVEL_LEADER = 3
};

enum OperatingSystem_t
{
	CLIENTOS_LINUX = 0x01,
	CLIENTOS_WINDOWS = 0x02
};

enum RaceType_t
{
	RACE_NONE	= 0,
	RACE_VENOM 	= 1,
	RACE_BLOOD	= 2,
	RACE_UNDEAD	= 3,
	RACE_FIRE	= 4
};

enum CombatType_t
{
	COMBAT_NONE		= 0,
	COMBAT_PHYSICALDAMAGE	= 1,
	COMBAT_ENERGYDAMAGE	= 2,
	COMBAT_EARTHDAMAGE	= 4,
	COMBAT_FIREDAMAGE	= 8,
	COMBAT_UNDEFINEDDAMAGE	= 16,
	COMBAT_LIFEDRAIN	= 32,
	COMBAT_MANADRAIN	= 64,
	COMBAT_HEALING		= 128,
	COMBAT_DROWNDAMAGE	= 256,
	COMBAT_ICEDAMAGE	= 512,
	COMBAT_HOLYDAMAGE	= 1024,
	COMBAT_DEATHDAMAGE      = 2048
};

enum CombatParam_t
{
	COMBATPARAM_COMBATTYPE = 1,
	COMBATPARAM_EFFECT = 2,
	COMBATPARAM_DISTANCEEFFECT = 3,
	COMBATPARAM_BLOCKEDBYSHIELD = 4,
	COMBATPARAM_BLOCKEDBYARMOR = 5,
	COMBATPARAM_TARGETCASTERORTOPMOST = 6,
	COMBATPARAM_CREATEITEM = 7,
	COMBATPARAM_AGGRESSIVE = 8,
	COMBATPARAM_DISPEL = 9,
	COMBATPARAM_USECHARGES = 10
};

enum CallBackParam_t
{
	CALLBACKPARAM_LEVELMAGICVALUE = 1,
	CALLBACKPARAM_SKILLVALUE = 2,
	CALLBACKPARAM_TARGETTILECALLBACK = 3,
	CALLBACKPARAM_TARGETCREATURECALLBACK = 4
};

enum ConditionParam_t
{
	CONDITIONPARAM_OWNER = 1,
	CONDITIONPARAM_TICKS = 2,
	//CONDITIONPARAM_OUTFIT = 3,

	CONDITIONPARAM_HEALTHGAIN = 4,
	CONDITIONPARAM_HEALTHTICKS = 5,
	CONDITIONPARAM_MANAGAIN = 6,
	CONDITIONPARAM_MANATICKS = 7,
	CONDITIONPARAM_DELAYED = 8,
	CONDITIONPARAM_SPEED = 9,
	CONDITIONPARAM_LIGHT_LEVEL = 10,
	CONDITIONPARAM_LIGHT_COLOR = 11,
	CONDITIONPARAM_SOULGAIN = 12,
	CONDITIONPARAM_SOULTICKS = 13,
	CONDITIONPARAM_MINVALUE = 14,
	CONDITIONPARAM_MAXVALUE = 15,
	CONDITIONPARAM_STARTVALUE = 16,
	CONDITIONPARAM_TICKINTERVAL = 17,
	CONDITIONPARAM_FORCEUPDATE = 18,
	CONDITIONPARAM_SKILL_MELEE = 19,
	CONDITIONPARAM_SKILL_FIST = 20,
	CONDITIONPARAM_SKILL_CLUB = 21,
	CONDITIONPARAM_SKILL_SWORD = 22,
	CONDITIONPARAM_SKILL_AXE = 23,
	CONDITIONPARAM_SKILL_DISTANCE = 24,
	CONDITIONPARAM_SKILL_SHIELD = 25,
	CONDITIONPARAM_SKILL_FISHING = 26,
	CONDITIONPARAM_STAT_MAXHEALTH = 27,
	CONDITIONPARAM_STAT_MAXMANA = 28,
	CONDITIONPARAM_STAT_SOUL = 29,
	CONDITIONPARAM_STAT_MAGICLEVEL = 30,
	CONDITIONPARAM_STAT_MAXHEALTHPERCENT = 31,
	CONDITIONPARAM_STAT_MAXMANAPERCENT = 32,
	CONDITIONPARAM_STAT_SOULPERCENT = 33,
	CONDITIONPARAM_STAT_MAGICLEVELPERCENT = 34,
	CONDITIONPARAM_PERIODICDAMAGE = 35,
	CONDITIONPARAM_SKILL_SOUND = 36
};

enum BlockType_t
{
	BLOCK_NONE = 0,
	BLOCK_DEFENSE,
	BLOCK_ARMOR,
	BLOCK_IMMUNITY
};

enum skills_t
{
	SKILL_FIRST = 0,
	SKILL_FIST = SKILL_FIRST,
	SKILL_CLUB = 1,
	SKILL_SWORD = 2,
	SKILL_AXE = 3,
	SKILL_DIST = 4,
	SKILL_SHIELD = 5,
	SKILL_FISH = 6,
	MAGLEVEL = 7,
	LEVEL = 8,
	SKILL_LAST = SKILL_FISH
};

enum stats_t
{
	STAT_FIRST = 0,
	STAT_MAXHEALTH = STAT_FIRST,
	STAT_MAXMANA,
	STAT_SOUL,
	STAT_MAGICLEVEL,
	STAT_LAST = STAT_MAGICLEVEL
};

enum lossTypes_t
{
	LOSS_FIRST = 0,
	LOSS_EXPERIENCE = LOSS_FIRST,
	LOSS_MANASPENT = 1,
	LOSS_SKILLTRIES = 2,
	LOSS_ITEMS = 3,
	LOSS_LAST = LOSS_ITEMS
};

enum formulaType_t
{
	FORMULA_UNDEFINED = 0,
	FORMULA_LEVELMAGIC = 1,
	FORMULA_SKILL = 2,
	FORMULA_VALUE = 3
};

enum ConditionId_t
{
	CONDITIONID_DEFAULT = -1,
	CONDITIONID_COMBAT = 0,
	CONDITIONID_HEAD = 1,
	CONDITIONID_NECKLACE = 2,
	CONDITIONID_BACKPACK = 3,
	CONDITIONID_ARMOR = 4,
	CONDITIONID_RIGHT = 5,
	CONDITIONID_LEFT = 6,
	CONDITIONID_LEGS = 7,
	CONDITIONID_FEET = 8,
	CONDITIONID_RING = 9,
	CONDITIONID_AMMO = 10
};

enum PlayerSex_t
{
	PLAYERSEX_FEMALE = 0,
	PLAYERSEX_MALE = 1
};

enum CharacterTypes_t
{
	PLAYER_MALE_1 = 0x80,
	PLAYER_MALE_2 = 0x81,
	PLAYER_MALE_3 = 0x82,
	PLAYER_MALE_4 = 0x83,
	PLAYER_MALE_5 = 0x84,
	PLAYER_MALE_6 = 0x85,
	PLAYER_MALE_7 = 0x86,
	PLAYER_FEMALE_1 = 0x88,
	PLAYER_FEMALE_2 = 0x89,
	PLAYER_FEMALE_3 = 0x8A,
	PLAYER_FEMALE_4 = 0x8B,
	PLAYER_FEMALE_5 = 0x8C,
	PLAYER_FEMALE_6 = 0x8D,
	PLAYER_FEMALE_7 = 0x8E,
};

struct Outfit_t
{
	Outfit_t()
	{
		lookHead   = 0;
		lookBody   = 0;
		lookLegs   = 0;
		lookFeet   = 0;
		lookType   = 0;
		lookTypeEx = 0;
		lookAddons = 0;
	}

	uint16_t lookType;
	uint16_t lookTypeEx;
	uint8_t lookHead;
	uint8_t lookBody;
	uint8_t lookLegs;
	uint8_t lookFeet;
	uint8_t lookAddons;
};

struct LightInfo
{
	uint32_t level;
	uint32_t color;
	LightInfo()
	{
		level = 0;
		color = 0;
	}
	LightInfo(uint32_t _level, uint32_t _color)
	{
		level = _level;
		color = _color;
	}
};

struct ShopInfo
{
	uint32_t itemId;
	uint32_t subType;
	uint32_t buyPrice;
	uint32_t sellPrice;
	std::string itemName;

	ShopInfo()
	{
		itemId = 0;
		subType = 1;
		buyPrice = 0;
		sellPrice = 0;
		itemName = "";
	}

	ShopInfo(uint32_t _itemId, int32_t _subType = 0, uint32_t _buyPrice = 0, uint32_t _sellPrice = 0,
		const std::string& _itemName = "") : itemId(_itemId), subType(_subType), buyPrice(_buyPrice),
		sellPrice(_sellPrice), itemName(_itemName) {}
};

typedef std::list<ShopInfo> ShopInfoList;
#endif
Same thing for the rest..
here is chat.cpp
Code:
//////////////////////////////////////////////////////////////////////
// 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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//////////////////////////////////////////////////////////////////////
#include "otpch.h"

#include "chat.h"
#include "configmanager.h"
#include "player.h"
#include "game.h"
#include "iologindata.h"

extern ConfigManager g_config;
extern Game g_game;

PrivateChatChannel::PrivateChatChannel(uint16_t channelId, std::string channelName) :
	ChatChannel(channelId, channelName)
{
	m_owner = 0;
}

bool PrivateChatChannel::isInvited(const Player* player)
{
	if(!player)
		return false;

	if(player->getGUID() == getOwner())
		return true;

	InvitedMap::iterator it = m_invites.find(player->getGUID());
	if(it != m_invites.end())
		return true;

	return false;
}

bool PrivateChatChannel::addInvited(Player* player)
{
	InvitedMap::iterator it = m_invites.find(player->getGUID());
	if(it != m_invites.end())
		return false;

	m_invites[player->getGUID()] = player;
	return true;
}

bool PrivateChatChannel::removeInvited(Player* player)
{
	InvitedMap::iterator it = m_invites.find(player->getGUID());
	if(it == m_invites.end())
		return false;

	m_invites.erase(it);
	return true;
}

void PrivateChatChannel::invitePlayer(Player* player, Player* invitePlayer)
{
	if(player != invitePlayer && addInvited(invitePlayer))
	{
		std::string msg;
		msg = player->getName();
		msg += " invites you to ";
		msg += (player->getSex() == PLAYERSEX_FEMALE ? "her" : "his");
		msg += " private chat channel.";
		invitePlayer->sendTextMessage(MSG_INFO_DESCR, msg.c_str());

		msg = invitePlayer->getName();
		msg += " has been invited.";
		player->sendTextMessage(MSG_INFO_DESCR, msg.c_str());
	}
}

void PrivateChatChannel::excludePlayer(Player* player, Player* excludePlayer)
{
	if(player != excludePlayer && removeInvited(excludePlayer))
	{
		removeUser(excludePlayer);

		std::string msg;
		msg = excludePlayer->getName();
		msg += " has been excluded.";
		player->sendTextMessage(MSG_INFO_DESCR, msg.c_str());

		excludePlayer->sendClosePrivate(getId());
	}
}

void PrivateChatChannel::closeChannel()
{
	for(UsersMap::iterator cit = m_users.begin(); cit != m_users.end(); ++cit)
	{
		if(Player* toPlayer = cit->second->getPlayer())
			toPlayer->sendClosePrivate(getId());
	}
}

ChatChannel::ChatChannel(uint16_t channelId, std::string channelName)
{
	m_id = channelId;
	m_name = channelName;
}

bool ChatChannel::addUser(Player* player)
{
	UsersMap::iterator it = m_users.find(player->getID());
	if(it != m_users.end())
		return false;

	switch(m_id)
	{
		case 0x00:
		{
			uint32_t playerId = player->getID();
			uint32_t guildId = player->getGuildId();
			if(IOGuild::getInstance()->getMotd(player->getGuildId()).length())
				Scheduler::getScheduler().addEvent(createSchedulerTask(150, boost::bind(&Game::sendGuildMotd, &g_game, playerId, guildId)));
			break;
		}

		case 0x01:
			if(!player->hasCustomFlag(PlayerCustomFlag_CanSeeStaffChannel))
				return false;
			break;

		case 0x02:
			if(!player->hasCustomFlag(PlayerCustomFlag_CanSeeCounsellorChannel))
				return false;
			break;

		case 0x03:
			if(!player->hasFlag(PlayerFlag_CanAnswerRuleViolations))
				return false;
			break;

		case 0x05:
			if(!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) && player->getVocationId() == 0)
				return false;
			break;

		case 0x06:
			if(!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) && player->getVocationId() != 0)
				return false;
			break;
	}

	m_users[player->getID()] = player;
	return true;
}

bool ChatChannel::removeUser(Player* player)
{
	UsersMap::iterator it = m_users.find(player->getID());
	if(it == m_users.end())
		return false;

	m_users.erase(it);
	return true;
}

bool ChatChannel::talk(Player* fromPlayer, SpeakClasses type, const std::string& text, uint32_t time /*= 0*/)
{
	if(!fromPlayer->hasFlag(PlayerFlag_CannotBeMuted) && (m_id == 0x05 || m_id == 0x06))
	{
		Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_TRADETICKS, 120000, 0);
		fromPlayer->addCondition(condition);
	}

	bool success = false;
	Player* tmpPlayer = NULL;
	for(UsersMap::iterator it = m_users.begin(); it != m_users.end(); ++it)
	{
		if((tmpPlayer = it->second->getPlayer()))
		{
			tmpPlayer->sendToChannel(fromPlayer, type, text, m_id, time);
			success = true;
		}
	}
	return success;
}

Chat::Chat()
{
	// Create the default channels
	ChatChannel *newChannel;

	newChannel = new ChatChannel(0x01, "Staff");
	if(newChannel)
		m_normalChannels[0x01] = newChannel;

	newChannel = new ChatChannel(0x02, "Counsellor");
	if(newChannel)
		m_normalChannels[0x02] = newChannel;

	newChannel = new ChatChannel(0x03, "Rule Violations");
	if(newChannel)
		m_normalChannels[0x03] = newChannel;

	newChannel = new ChatChannel(0x04, "Game-Chat");
	if(newChannel)
		m_normalChannels[0x04] = newChannel;

	newChannel = new ChatChannel(0x05, "Trade");
	if(newChannel)
		m_normalChannels[0x05] = newChannel;

	newChannel = new ChatChannel(0x06, "Trade-Rookgaard");
	if(newChannel)
		m_normalChannels[0x06] = newChannel;

	newChannel = new ChatChannel(0x07, "RL-Chat");
	if(newChannel)
		m_normalChannels[0x07] = newChannel;

	newChannel = new ChatChannel(0x08, "Help");
	if(newChannel)
		m_normalChannels[0x08] = newChannel;

	newChannel = new PrivateChatChannel(0xFFFF, "Private Chat Channel");
	if(newChannel)
		dummyPrivate = newChannel;
}

Chat::~Chat()
{
	delete dummyPrivate;

	for(NormalChannelMap::iterator it = m_normalChannels.begin(); it != m_normalChannels.end(); ++it)
		delete it->second;
	m_normalChannels.clear();

	for(GuildChannelMap::iterator it = m_guildChannels.begin(); it != m_guildChannels.end(); ++it)
		delete it->second;
	m_guildChannels.clear();

	for(PrivateChannelMap::iterator it = m_privateChannels.begin(); it != m_privateChannels.end(); ++it)
		delete it->second;
	m_privateChannels.clear();
}

ChatChannel* Chat::createChannel(Player* player, uint16_t channelId)
{
	if(getChannel(player, channelId))
		return NULL;

	if(channelId == 0x00)
	{
		ChatChannel* newChannel = new ChatChannel(channelId, player->getGuildName());
		if(!newChannel)
			return NULL;

		m_guildChannels[player->getGuildId()] = newChannel;
		return newChannel;
	}
	else if(channelId == 0xFFFF)
	{
		//only 1 private channel for each premium player
		if(!player->isPremium() || getPrivateChannel(player))
			return NULL;

		//find a free private channel slot
		for(uint16_t i = 100; i < 10000; ++i)
		{
			if(m_privateChannels.find(i) == m_privateChannels.end())
			{
				PrivateChatChannel* newChannel = new PrivateChatChannel(i, player->getName() + "'s Channel");
				if(!newChannel)
					return NULL;

				newChannel->setOwner(player->getGUID());

				m_privateChannels[i] = newChannel;
				return newChannel;
			}
		}
	}
	return NULL;
}

bool Chat::deleteChannel(Player* player, uint16_t channelId)
{
	if(channelId == 0x00)
	{
		GuildChannelMap::iterator it = m_guildChannels.find(player->getGuildId());
		if(it == m_guildChannels.end())
			return false;

		delete it->second;
		m_guildChannels.erase(it);
		return true;
	}
	else
	{
		PrivateChannelMap::iterator it = m_privateChannels.find(channelId);
		if(it == m_privateChannels.end())
			return false;

		it->second->closeChannel();

		delete it->second;
		m_privateChannels.erase(it);
		return true;
	}
	return false;
}

bool Chat::addUserToChannel(Player* player, uint16_t channelId)
{
	ChatChannel* channel = getChannel(player, channelId);
	if(!channel || !player)
		return false;

	return channel->addUser(player);
}

bool Chat::removeUserFromChannel(Player* player, uint16_t channelId)
{
	ChatChannel* channel = getChannel(player, channelId);
	if(!channel || !player)
		return false;

	if(channel->removeUser(player))
	{
		if(channel->getOwner() == player->getGUID())
			deleteChannel(player, channelId);
		return true;
	}
	else
		return false;
}

void Chat::removeUserFromAllChannels(Player* player)
{
	if(!player)
		return;

	ChannelList list = getChannelList(player);
	while(list.size())
	{
		ChatChannel* channel = list.front();
		list.pop_front();
		channel->removeUser(player);
		if(channel->getOwner() == player->getGUID())
			deleteChannel(player, channel->getId());
	}
}

bool Chat::talkToChannel(Player* player, SpeakClasses type, const std::string& text, uint16_t channelId)
{
	ChatChannel* channel = getChannel(player, channelId);
	if(!channel || !player)
		return false;

	if(!player->hasFlag(PlayerFlag_CannotBeMuted))
	{
		if(player->hasCondition(CONDITION_TRADETICKS) && (channelId == 0x05 || channelId == 0x06))
		{
			player->sendCancel("You may only place one offer in two minutes.");
			return false;
		}
		else if(player->getLevel() < 2 && channelId < 0x08)
		{
			player->sendCancel("You may not speak into channels as long as you are on level 1.");
			return false;
		}
	}

	if(channelId == 0x00)
	{
		if(g_config.getBool(ConfigManager::INGAME_GUILD_MANAGEMENT))
		{
			if(text == "!disband" || text.substr(0, 7) == "!invite" || text == "!leave" || text.substr(0, 5) == "!kick" || text.substr(0, 7) == "!revoke" || text.substr(0, 7) == "!demote" || text.substr(0, 8) == "!promote" || text.substr(0, 15) == "!passleadership" || text.substr(0, 5) == "!nick" || text.substr(0, 12) == "!setrankname" || text.substr(0, 8) == "!setmotd" || text == "!cleanmotd" || text == "!commands")
			{
				if(player->getGuildId())
				{
					if(IOGuild::getInstance()->guildExists(player->getGuildId()))
					{
						char buffer[350];
						ChatChannel* guildChannel = getChannel(player, 0x00);
						if(!guildChannel)
							return false;

						if(text == "!disband")
						{
							if(player->getGuildLevel() == GUILDLEVEL_LEADER)
							{
								uint32_t guildId = player->getGuildId();
								guildChannel->talk(player, SPEAK_CHANNEL_R2, "The guild has been disbanded.");
								IOGuild::getInstance()->disbandGuild(guildId);
							}
							else
								player->sendCancel("You are not the leader of your guild.");
						}
						else if(text.substr(0, 7) == "!invite")
						{
							if(player->getGuildLevel() > GUILDLEVEL_MEMBER)
							{
								if(text.length() > 8)
								{
									std::string param = text.substr(8);
									trimString(param);
									Player* paramPlayer = g_game.getPlayerByName(param);
									if(paramPlayer)
									{
										if(paramPlayer->getGuildId() == 0)
										{
											if(!paramPlayer->isInvitedToGuild(player->getGuildId()))
											{
												sprintf(buffer, "%s has invited you to join the guild, %s.", player->getName().c_str(), player->getGuildName().c_str());
												paramPlayer->sendTextMessage(MSG_INFO_DESCR, buffer);
												sprintf(buffer, "%s has invited %s to the guild.", player->getName().c_str(), paramPlayer->getName().c_str());
												guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
												paramPlayer->invitedToGuildsList.push_back(player->getGuildId());
											}
											else
												player->sendCancel("A player with that name has already been invited to your guild.");
										}
										else
											player->sendCancel("A player with that name is already in a guild.");
									}
									else if(IOLoginData::getInstance()->playerExists(param))
									{
										uint32_t guid;
										IOLoginData::getInstance()->getGuidByName(guid, param);
										if(!IOGuild::getInstance()->hasGuild(guid))
										{
											if(!IOGuild::getInstance()->isInvitedToGuild(guid, player->getGuildId()))
											{
												if(IOGuild::getInstance()->guildExists(player->getGuildId()))
												{
													IOGuild::getInstance()->invitePlayerToGuild(guid, player->getGuildId());
													sprintf(buffer, "%s has invited %s to the guild.", player->getName().c_str(), param.c_str());
													guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
												}
												else
													player->sendCancel("Your guild does not exist anymore.");
											}
											else
												player->sendCancel("A player with that name has already been invited to your guild.");
										}
										else
											player->sendCancel("A player with that name is already in a guild.");
									}
									else
										player->sendCancel("A player with that name does not exist.");
								}
								else
									player->sendCancel("Invalid guildcommand parameters.");
							}
							else
								player->sendCancel("You don't have rights to invite players to your guild.");
						}
						else if(text == "!leave")
						{
							if(player->getGuildLevel() < GUILDLEVEL_LEADER)
							{
								sprintf(buffer, "%s has left the guild.", player->getName().c_str());
								guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
								player->resetGuildInformation();
							}
							else
								player->sendCancel("You cannot leave your guild because you are the leader of it, you have to pass the leadership to another member of your guild or disband the guild.");
						}
						else if(text.substr(0, 7) == "!revoke")
						{
							if(player->getGuildLevel() > GUILDLEVEL_MEMBER)
							{
								if(text.length() > 8)
								{
									std::string param = text.substr(8);
									trimString(param);
									Player* paramPlayer = g_game.getPlayerByName(param);
									if(paramPlayer)
									{
										if(paramPlayer->getGuildId() == 0)
										{
											InvitedToGuildsList::iterator it = std::find(paramPlayer->invitedToGuildsList.begin(),paramPlayer->invitedToGuildsList.end(), player->getGuildId());
											if(it != paramPlayer->invitedToGuildsList.end())
											{
												sprintf(buffer, "%s has revoked your invite to %s guild.", player->getName().c_str(), (player->getSex() == PLAYERSEX_FEMALE ? "her" : "his"));
												paramPlayer->sendTextMessage(MSG_INFO_DESCR, buffer);
												sprintf(buffer, "%s has revoked the guildinvite of %s.", player->getName().c_str(), paramPlayer->getName().c_str());
												guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
												paramPlayer->invitedToGuildsList.erase(it);
												return true;
											}
											else
												player->sendCancel("A player with that name is not invited to your guild.");
										}
										else
											player->sendCancel("A player with that name is already in a guild.");
									}
									else if(IOLoginData::getInstance()->playerExists(param))
									{
										uint32_t guid;
										IOLoginData::getInstance()->getGuidByName(guid, param);
										if(IOGuild::getInstance()->isInvitedToGuild(guid, player->getGuildId()))
										{
											if(IOGuild::getInstance()->guildExists(player->getGuildId()))
											{
												sprintf(buffer, "%s has revoked the guildinvite of %s.", player->getName().c_str(), param.c_str());
												guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
												IOGuild::getInstance()->revokeGuildInvite(guid, player->getGuildId());
											}
											else
												player->sendCancel("It seems like your guild does not exist anymore.");
										}
										else
											player->sendCancel("A player with that name is not invited to your guild.");
									}
									else
										player->sendCancel("A player with that name does not exist.");
								}
								else
									player->sendCancel("Invalid guildcommand parameters.");
							}
							else
								player->sendCancel("You don't have rights to revoke an invite of someone in your guild.");
						}
						else if(text.substr(0, 8) == "!promote" || text.substr(0, 7) == "!demote" || text.substr(0, 15) == "!passleadership" || text.substr(0, 5) == "!kick")
						{
							if(player->getGuildLevel() == GUILDLEVEL_LEADER)
							{
								std::string param;
								uint32_t length = 0;
								if(text[2] == 'r')
									length = 11;
								else if(text[2] == 'e')
									length = 10;
								else if(text[2] == 'a')
									length = 18;
								else
									length = 8;
								if(text.length() < length)
								{
									player->sendCancel("Invalid guildcommand parameters.");
									return false;
								}
								else
									length -= 2;
								param = text.substr(length);
								trimString(param);
								Player* paramPlayer = g_game.getPlayerByName(param);
								if(paramPlayer)
								{
									if(paramPlayer->getGuildId())
									{
										if(IOGuild::getInstance()->guildExists(paramPlayer->getGuildId()))
										{
											if(player->getGuildId() == paramPlayer->getGuildId())
											{
												if(text[2] == 'r')
												{
													if(paramPlayer->getGuildLevel() == GUILDLEVEL_MEMBER)
													{
														if(paramPlayer->isPremium())
														{
															paramPlayer->setGuildLevel(GUILDLEVEL_VICE);
															sprintf(buffer, "%s has promoted %s to %s.", player->getName().c_str(), paramPlayer->getName().c_str(), paramPlayer->getGuildRank().c_str());
															guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
														}
														else
															player->sendCancel("A player with that name does not have a premium account.");
													}
													else
														player->sendCancel("You can only promote Members to Vice-Leaders.");
												}
												else if(text[2] == 'e')
												{
													if(paramPlayer->getGuildLevel() == GUILDLEVEL_VICE)
													{
														paramPlayer->setGuildLevel(GUILDLEVEL_MEMBER);
														sprintf(buffer, "%s has demoted %s to %s.", player->getName().c_str(), paramPlayer->getName().c_str(), paramPlayer->getGuildRank().c_str());
														guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
													}
													else
														player->sendCancel("You can only demote Vice-Leaders to Members.");
												}
												else if(text[2] == 'a')
												{
													if(paramPlayer->getGuildLevel() == GUILDLEVEL_VICE)
													{
														const uint32_t levelToFormGuild = g_config.getNumber(ConfigManager::LEVEL_TO_FORM_GUILD);
														if(paramPlayer->getLevel() >= levelToFormGuild)
														{
															paramPlayer->setGuildLevel(GUILDLEVEL_LEADER);
															player->setGuildLevel(GUILDLEVEL_VICE);
															IOGuild::getInstance()->updateOwnerId(paramPlayer->getGuildId(), paramPlayer->getGUID());
															sprintf(buffer, "%s has passed the guild leadership to %s.", player->getName().c_str(), paramPlayer->getName().c_str());
															guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
														}
														else
														{
															sprintf(buffer, "The new guild leader has to be at least Level %d.", levelToFormGuild);
															player->sendCancel(buffer);
														}
													}
													else
														player->sendCancel("A player with that name is not a Vice-Leader.");
												}
												else
												{
													if(player->getGuildLevel() > paramPlayer->getGuildLevel())
													{
														sprintf(buffer, "%s has been kicked from the guild by %s.", paramPlayer->getName().c_str(), player->getName().c_str());
														guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
														paramPlayer->resetGuildInformation();
													}
													else
														player->sendCancel("You may only kick players with a guild rank below your.");
												}
											}
											else
												player->sendCancel("You are not in the same guild as a player with that name.");
										}
										else
											player->sendCancel("Could not find the guild of a player with that name.");
									}
									else
										player->sendCancel("A player with that name is not in a guild.");
								}
								else if(IOLoginData::getInstance()->playerExists(param))
								{
									uint32_t guid;
									IOLoginData::getInstance()->getGuidByName(guid, param);
									if(IOGuild::getInstance()->hasGuild(guid))
									{
										if(player->getGuildId() == IOGuild::getInstance()->getGuildId(guid))
										{
											if(text[2] == 'r')
											{
												if(IOGuild::getInstance()->getGuildLevel(guid) == GUILDLEVEL_MEMBER)
												{
													if(IOLoginData::getInstance()->isPremium(guid))
													{
														IOGuild::getInstance()->setGuildLevel(guid, GUILDLEVEL_VICE);
														sprintf(buffer, "%s has promoted %s to %s.", player->getName().c_str(), param.c_str(), IOGuild::getInstance()->getRankName(IOGuild::getInstance()->getGuildLevel(guid), IOGuild::getInstance()->getGuildId(guid)).c_str());
														guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
													}
													else
														player->sendCancel("A player with that name does not have a premium account.");
												}
												else
													player->sendCancel("You can only promote Members to Vice-Leaders.");
											}
											else if(text[2] == 'e')
											{
												if(IOGuild::getInstance()->getGuildLevel(guid) == GUILDLEVEL_VICE)
												{
													IOGuild::getInstance()->setGuildLevel(guid, GUILDLEVEL_MEMBER);
													sprintf(buffer, "%s has demoted %s to %s.", player->getName().c_str(), param.c_str(), IOGuild::getInstance()->getRankName(IOGuild::getInstance()->getGuildLevel(guid), IOGuild::getInstance()->getGuildId(guid)).c_str());
													guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
												}
												else
													player->sendCancel("You can only demote Vice-Leaders to Members.");
											}
											else if(text[2] == 'a')
											{
												if(IOGuild::getInstance()->getGuildLevel(guid) == GUILDLEVEL_VICE)
												{
													const uint32_t levelToFormGuild = g_config.getNumber(ConfigManager::LEVEL_TO_FORM_GUILD);
													if(IOLoginData::getInstance()->getLevel(guid) >= levelToFormGuild)
													{
														IOGuild::getInstance()->setGuildLevel(guid, GUILDLEVEL_LEADER);
														player->setGuildLevel(GUILDLEVEL_VICE);
														sprintf(buffer, "%s has passed the guild leadership to %s.", player->getName().c_str(), param.c_str());
														guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
													}
													else
													{
														sprintf(buffer, "The new guild leader has to be at least Level %d.", levelToFormGuild);
														player->sendCancel(buffer);
													}
												}
												else
													player->sendCancel("A player with that name is not a Vice-Leader.");
											}
											else
											{
												sprintf(buffer, "%s has been kicked from the guild by %s.", param.c_str(), player->getName().c_str());
												guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
												IOLoginData::getInstance()->resetGuildInformation(guid);
											}
										}
									}
									else
										player->sendCancel("A player with that name is not in a guild");
								}
								else
									player->sendCancel("A player with that name does not exist.");
							}
							else
								player->sendCancel("You are not the leader of your guild.");
						}
						else if(text.substr(0, 5) == "!nick")
						{
							if(text.length() > 7)
							{
								std::string param = text.substr(6);
								boost::char_separator<char> sep(",");
								tokenizer cmdtokens(param, sep);
								tokenizer::iterator cmdit = cmdtokens.begin();
								std::string param1, param2;
								param1 = parseParams(cmdit, cmdtokens.end());
								param2 = parseParams(cmdit, cmdtokens.end());
								trimString(param1);
								trimString(param2);
								Player* paramPlayer = g_game.getPlayerByName(param1);
								if(paramPlayer)
								{
									if(paramPlayer->getGuildId())
									{
										if(param2.length() > 3)
										{
											if(param2.length() < 15)
											{
												if(isValidName(param2, false))
												{
													if(IOGuild::getInstance()->guildExists(paramPlayer->getGuildId()))
													{
														if(player->getGuildId() == paramPlayer->getGuildId())
														{
															if(paramPlayer->getGuildLevel() < player->getGuildLevel() || (player == paramPlayer && player->getGuildLevel() > GUILDLEVEL_MEMBER))
															{
																paramPlayer->setGuildNick(param2);
																if(player != paramPlayer)
																	sprintf(buffer, "%s has set the guildnick of %s to \"%s\".", player->getName().c_str(), paramPlayer->getName().c_str(), param2.c_str());
																else
																	sprintf(buffer, "%s has set %s guildnick to \"%s\".", player->getName().c_str(), (player->getSex() == PLAYERSEX_FEMALE ? "her" : "his"), param2.c_str());
																guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
															}
															else
																player->sendCancel("You may only change the guild nick of players that have a lower rank than you.");
														}
														else
															player->sendCancel("A player with that name is not in your guild.");
													}
													else
														player->sendCancel("A player with that name's guild could not be found.");
												}
												else
													player->sendCancel("That guildnick is not valid");
											}
											else
												player->sendCancel("That guildnick is too long, please select a shorter one.");
										}
										else
											player->sendCancel("That guildnick is too short, please select a longer one.");
									}
									else
										player->sendCancel("A player with that name is not in a guild.");
								}
								else if(IOLoginData::getInstance()->playerExists(param1))
								{
									uint32_t guid;
									IOLoginData::getInstance()->getGuidByName(guid, (std::string&)param1);
									if(IOGuild::getInstance()->hasGuild(guid))
									{
										if(param2.length() > 3)
										{
											if(param2.length() < 15)
											{
												if(isValidName(param2, false))
												{
													if(IOGuild::getInstance()->guildExists(guid))
													{
														if(player->getGuildId() == IOGuild::getInstance()->getGuildId(guid))
														{
															if(IOGuild::getInstance()->getGuildLevel(guid) < player->getGuildLevel())
															{
																IOGuild::getInstance()->setGuildNick(guid, param2);
																sprintf(buffer, "%s has set the guildnick of %s to \"%s\".", player->getName().c_str(), param1.c_str(), param2.c_str());
																guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
															}
															else
																player->sendCancel("You may only change the guild nick of players that have a lower rank than you.");
														}
														else
															player->sendCancel("A player with that name is not in your guild.");
													}
													else
														player->sendCancel("A player with that name's guild could not be found.");
												}
												else
													player->sendCancel("That guildnick is not valid");
											}
											else
												player->sendCancel("That guildnick is too long, please select a shorter one.");
										}
										else
											player->sendCancel("That guildnick is too short, please select a longer one.");
									}
									else
										player->sendCancel("A player with that name is not in any guild");
								}
								else
									player->sendCancel("A player with that name does not exist.");
							}
							else
								player->sendCancel("Invalid guildcommand parameters");
						}
						else if(text.substr(0, 12) == "!setrankname")
						{
							if(text.length() > 14)
							{
								std::string param = text.substr(13);
								boost::char_separator<char> sep(",");
								tokenizer cmdtokens(param, sep);
								tokenizer::iterator cmdit = cmdtokens.begin();
								std::string param1, param2;
								param1 = parseParams(cmdit, cmdtokens.end());
								param2 = parseParams(cmdit, cmdtokens.end());
								trimString(param1);
								trimString(param2);
								if(player->getGuildLevel() == GUILDLEVEL_LEADER)
								{
									if(param2.length() > 3)
									{
										if(param2.length() < 21)
										{
											if(isValidName(param2, false))
											{
												if(IOGuild::getInstance()->rankNameExists(param1, player->getGuildId()))
												{
													if(!IOGuild::getInstance()->rankNameExists(param2, player->getGuildId()))
													{
														IOGuild::getInstance()->changeRankName(param1, param2, player->getGuildId());
														sprintf(buffer, "%s has renamed the guildrank: \"%s\", to: \"%s\".", player->getName().c_str(), param1.c_str(), param2.c_str());
														guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
													}
													else
														player->sendCancel("There is already a rank in your guild with that name");
												}
												else
													player->sendCancel("There is no such rankname in your guild");
											}
											else
												player->sendCancel("The new guildrank contains invalid characters");
										}
										else
											player->sendCancel("The new rankname is too long.");
									}
									else
										player->sendCancel("The new rankname is too short.");
								}
								else
									player->sendCancel("You are not the leader of your guild.");
							}
							else
								player->sendCancel("Invalid guildcommand parameters");
						}
						else if(text.substr(0, 8) == "!setmotd")
						{
							if(player->getGuildLevel() == GUILDLEVEL_LEADER)
							{
								if(text.length() > 9)
								{
									std::string param = text.substr(9);
									trimString(param);
									if(param.length() > 3)
									{
										if(param.length() < 225)
										{
											IOGuild::getInstance()->setMotd(player->getGuildId(), param);
											sprintf(buffer, "%s has set the Message of the Day to: %s", player->getName().c_str(), param.c_str());
											guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
										}
										else
											player->sendCancel("That motd is too long.");
									}
									else
										player->sendCancel("That motd is too short.");
								}
								else
									player->sendCancel("Invalid guildcommand parameters");
							}
							else
								player->sendCancel("Only the leader of your guild can set the guild motd.");
						}
						else if(text == "!cleanmotd")
						{
							if(player->getGuildLevel() == GUILDLEVEL_LEADER)
							{
								IOGuild::getInstance()->setMotd(player->getGuildId(), "");
								sprintf(buffer, "%s has cleaned the Message of the Day.", player->getName().c_str());
								guildChannel->talk(player, SPEAK_CHANNEL_R2, buffer);
							}
							else
								player->sendCancel("Only the leader of your guild can clean the guild motd.");
						}
						else if(text == "!commands")
							player->sendToChannel(player, SPEAK_CHANNEL_R2, "The guild commands are: <!disband>, <!invite playerName>, <!leave>, <!kick playerName>, <!revoke playerName>, <!demote playerName>, <!promote playerName>, <!passleadership playerName>, <!nick playerName, nick>, <!setrankname oldRankName, newRankName>, <!setmotd newMotd> and <!cleanmotd>.", 0x00);
					}
					else
						player->sendCancel("It seems like your guild does not exist anymore.");
				}
				else
					player->sendCancel("You are not in a guild.");
				return true;
			}
		}

		switch(player->getGuildLevel())
		{
			case 2:
				type = SPEAK_CHANNEL_O;
				break;
			case 3:
				type = SPEAK_CHANNEL_R1;
				break;
			default:
				break;
		}
	}

	return channel->talk(player, type, text);
}

std::string Chat::getChannelName(Player* player, uint16_t channelId)
{
	if(ChatChannel* channel = getChannel(player, channelId))
		return channel->getName();
	else
		return "";
}

ChannelList Chat::getChannelList(Player* player)
{
	ChannelList list;
	bool gotPrivate = false;

	// If has guild
	if(player->getGuildId() && player->getGuildName().length())
	{
		if(ChatChannel* channel = getChannel(player, 0x00))
			list.push_back(channel);
		else if((channel = createChannel(player, 0x00)))
			list.push_back(channel);
	}

	for(NormalChannelMap::iterator nit = m_normalChannels.begin(); nit != m_normalChannels.end(); ++nit)
	{
		switch(nit->first)
		{
			case 0x01:
				if(!player->hasCustomFlag(PlayerCustomFlag_CanSeeStaffChannel))
					continue;
				break;

			case 0x02:
				if(!player->hasCustomFlag(PlayerCustomFlag_CanSeeCounsellorChannel))
					continue;
				break;

			case 0x03:
				if(!player->hasFlag(PlayerFlag_CanAnswerRuleViolations))
					continue;
				break;

			case 0x05:
				if(!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) && player->getVocationId() == 0)
					continue;
				break;

			case 0x06:
				if(!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) && player->getVocationId() != 0)
					continue;
				break;
		}

		list.push_back(nit->second);
	}

	for(PrivateChannelMap::iterator pit = m_privateChannels.begin(); pit != m_privateChannels.end(); ++pit)
	{
		if(PrivateChatChannel* channel = pit->second)
		{
			if(channel->isInvited(player))
				list.push_back(channel);

			if(channel->getOwner() == player->getGUID())
				gotPrivate = true;
		}
	}

	if(!gotPrivate && player->isPremium())
		list.push_front(dummyPrivate);

	return list;
}

ChatChannel* Chat::getChannel(Player* player, uint16_t channelId)
{
	if(channelId == 0x00)
	{
		GuildChannelMap::iterator git = m_guildChannels.find(player->getGuildId());
		if(git != m_guildChannels.end())
			return git->second;

		return NULL;
	}

	NormalChannelMap::iterator nit = m_normalChannels.find(channelId);
	if(nit != m_normalChannels.end())
	{
		switch(channelId)
		{
			case 0x01:
				if(!player->hasCustomFlag(PlayerCustomFlag_CanSeeStaffChannel))
					return NULL;
				break;

			case 0x02:
				if(!player->hasCustomFlag(PlayerCustomFlag_CanSeeCounsellorChannel))
					return NULL;
				break;

			case 0x03:
				if(!player->hasFlag(PlayerFlag_CanAnswerRuleViolations))
					return NULL;
				break;

			case 0x05:
				if(!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) && player->getVocationId() == 0)
					return NULL;
				break;

			case 0x06:
				if(!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) && player->getVocationId() != 0)
					return NULL;
				break;
		}
		return nit->second;
	}

	PrivateChannelMap::iterator pit = m_privateChannels.find(channelId);
	if(pit != m_privateChannels.end())
		return pit->second;

	return NULL;
}

ChatChannel* Chat::getChannelById(uint16_t channelId)
{
	NormalChannelMap::iterator it = m_normalChannels.find(channelId);
	if(it != m_normalChannels.end())
		return it->second;

	return NULL;
}

PrivateChatChannel* Chat::getPrivateChannel(Player* player)
{
	for(PrivateChannelMap::iterator it = m_privateChannels.begin(); it != m_privateChannels.end(); ++it)
	{
		if(PrivateChatChannel* channel = it->second)
		{
			if(channel->getOwner() == player->getGUID())
				return channel;
		}
	}
	return NULL;
}

in player.h what do you mean "in the public: (i put mine after the ghost stuff) add "

lol what version of TFS are you guys actually using, i used 0.2pl23, and also the newest 0.3 crying damson and it works wonderfully, if your enums.h does not have any CHANNELS, just replace where i put LOOT_CHANNEL with 0x10
 
Just a correction:

This:
PHP:
typedef std::map<uint32_t, ChatChannel*> LootChannelMap;

Should be defined before this:

PHP:
LootChannelMap m_lootChannels;

Else it will throw an error.
 
Just a correction:

This:
PHP:
typedef std::map<uint32_t, ChatChannel*> LootChannelMap;

Should be defined before this:

PHP:
LootChannelMap m_lootChannels;

Else it will throw an error.

true, i should probably state that, i guess me assuming people who assume to put things that look alike together is a stretch, thanks for that
 
To finish the talkactions thing just do the following things:

Talkactions.cpp


Find the following code:
Code:
{"showbanishmentinfo", &showBanishmentInfo}

Change it to:

Code:
{"showbanishmentinfo", &showBanishmentInfo},

(added a comma)

Below it add:

Code:
{"showloot", &showLoot}


Talkactions.h

Find:
Code:
		static TalkFunction showBanishmentInfo;

Below it add:
Code:
		static TalkFunction showLoot;

and you're done
 
Back
Top