Pastebin

New pastes are no longer accepted · Stats

Latest Pastes

map

/* $Id: map.cpp 186 2010-02-06 00:06:47Z sausage $
 * EOSERV is released under the zlib license.
 * See LICENSE.txt for more info.
 */

#include "map.hpp"

#include "arena.hpp"
#include "character.hpp"
#include "console.hpp"
#include "eoclient.hpp"
#include "eodata.hpp"
#include "eoserver.hpp"
#include "npc.hpp"
#include "packet.hpp"
#include "player.hpp"
#include "quest.hpp"
#include "timer.hpp"
#include "world.hpp"

static const char *safe_fail_filename;

static void safe_fail(int line)
{
	Console::Err("Invalid file / failed read/seek: %s -- %i", safe_fail_filename, line);
}

#define SAFE_SEEK(fh, offset, from) if (std::fseek(fh, offset, from) != 0) { std::fclose(fh); safe_fail(__LINE__); return false; }
#define SAFE_READ(buf, size, count, fh) if (std::fread(buf, size, count, fh) != static_cast<int>(count)) {  std::fclose(fh); safe_fail(__LINE__);return false; }

void map_spawn_chests(void *map_void)
{
	Map *map(static_cast<Map *>(map_void));

	double current_time = Timer::GetTime();
	UTIL_PTR_VECTOR_FOREACH(map->chests, Map_Chest, chest)
	{
		bool needs_update = false;

		for (int slot = 1; slot <= chest->slots; ++slot)
		{
			PtrList<Map_Chest_Spawn> spawns;

            UTIL_PTR_LIST_FOREACH(chest->spawns, Map_Chest_Spawn, spawn)
			{
				if (spawn->last_taken + spawn->time*60.0 < current_time)
				{
					bool slot_used = false;

					UTIL_PTR_LIST_FOREACH(chest->items, Map_Chest_Item, item)
					{
						if (item->slot == spawn->slot)
						{
							slot_used = true;
						}
					}

					if (!slot_used)
					{
						spawns.push_back(*spawn);
					}
				}
			}

			if (!spawns.empty())
			{

				PtrList<Map_Chest_Spawn>::Iterator it(spawns);
				int r = util::rand(0, spawns.size()-1);

				for (int i = 0; i < r; ++i)
				{
					++it;
				}

				Map_Chest_Spawn *spawn(*it);

				chest->AddItem(spawn->item->id, spawn->item->amount, spawn->slot);
				needs_update = true;

#ifdef DEBUG
				Console::Dbg("Spawning chest item %i (x%i) on map %i", spawn->item->id, spawn->item->amount, map->id);
#endif // DEBUG
			}
		}

		if (needs_update)
		{
			chest->Update(map, 0);
		}
	}
}

struct map_close_door_struct : public Shared
{
	Map *map;
	unsigned char x, y;
};

void map_close_door(void *map_close_door_struct_void)
{
	map_close_door_struct *close(static_cast<map_close_door_struct *>(map_close_door_struct_void));

	close->map->CloseDoor(close->x, close->y);

	close->Release();
}

int Map_Chest::AddItem(short item, int amount, int slot)
{
	if (amount <= 0)
	{
		return 0;
	}

	if (slot == 0)
	{
		UTIL_PTR_LIST_FOREACH(this->items, Map_Chest_Item, it)
		{
			if (it->id == item)
			{
				if (it->amount + amount < 0 || it->amount + amount > this->maxchest)
				{
					return 0;
				}

				it->amount += amount;
				return amount;
			}
		}
	}

	if (this->items.size() >= static_cast<std::size_t>(this->chestslots) || amount > this->maxchest)
	{
		return 0;
	}

	if (slot == 0)
	{
		int user_items = 0;

		UTIL_PTR_LIST_FOREACH(this->items, Map_Chest_Item, item)
		{
			if (item->slot == 0)
			{
				++user_items;
			}
		}

		if (user_items + this->slots >= this->chestslots)
		{
			return 0;
		}
	}

	Map_Chest_Item *chestitem(new Map_Chest_Item);
	chestitem->id = item;
	chestitem->amount = amount;
	chestitem->slot = slot;

	if (slot == 0)
	{

		this->items.push_back(chestitem);
	}
	else
	{
		this->items.push_front(chestitem);
	}

	return amount;
}

int Map_Chest::DelItem(short item)
{
	UTIL_PTR_LIST_FOREACH(this->items, Map_Chest_Item, it)
	{
		if (it->id == item)
		{
			int amount = it->amount;

			if (it->slot)
			{
				double current_time = Timer::GetTime();

				UTIL_PTR_LIST_FOREACH(this->spawns, Map_Chest_Spawn, spawn)
				{
					if (spawn->slot == it->slot)
					{
						spawn->last_taken = current_time;
					}
				}
			}

			this->items.erase(it);
			return amount;
		}
	}

	return false;
}

void Map_Chest::Update(Map *map, Character *exclude)
{
	PacketBuilder builder(PACKET_CHEST, PACKET_AGREE);

	UTIL_PTR_LIST_FOREACH(this->items, Map_Chest_Item, item)
	{
		builder.AddShort(item->id);
		builder.AddThree(item->amount);
	}

	UTIL_PTR_LIST_FOREACH(map->characters, Character, character)
	{
		if (*character == exclude)
		{
			continue;
		}

		if (util::path_length(character->x, character->y, this->x, this->y) <= 1)
		{
			character->player->client->SendBuilder(builder);
		}
	}
}

Map::Map(int id, World *world)
{
	this->id = id;
	this->world = world;
	this->exists = false;
	this->jukebox_protect = 0.0;
	this->arena = 0;

	this->LoadArena();

	this->Load();

	if (!this->chests.empty())
	{

		TimeEvent *event = new TimeEvent(map_spawn_chests, this, 60.0, Timer::FOREVER);
		this->world->timer.Register(event);
		event->Release();
	}
}

void Map::LoadArena()
{
	PtrList<Character> update_characters;

	if (this->arena)
	{
		UTIL_PTR_LIST_FOREACH(this->arena->map->characters, Character, character)
		{
			if (character->arena == this->arena)
			{
				update_characters.push_back(*character);
			}
		}

		delete this->arena;
	}

	if (world->arenas_config[util::to_string(id) + ".enabled"])
	{
		std::string spawns_str = world->arenas_config[util::to_string(id) + ".spawns"];

		std::vector<std::string> spawns = util::explode(',', spawns_str);

		if (spawns.size() % 4 != 0)
		{
			Console::Wrn("Invalid arena spawn data for map %i", id);
			this->arena = 0;
		}
		else
		{
			this->arena = new Arena(this, static_cast<int>(world->arenas_config[util::to_string(id) + ".time"]), static_cast<int>(world->arenas_config[util::to_string(id) + ".block"]));

			int i = 1;
			Arena_Spawn *s;
			UTIL_VECTOR_FOREACH_ALL(spawns, std::string, spawn)
			{
				util::trim(spawn);

				switch (i++ % 4)
				{
					case 1:
						s = new Arena_Spawn;
						s->sx = util::to_int(spawn);
						break;

					case 2:
						s->sy = util::to_int(spawn);
						break;

					case 3:
						s->dx = util::to_int(spawn);
						break;

					case 0:
						s->dy = util::to_int(spawn);
						this->arena->spawns.push_back(s);
						s->Release();
						break;

				}
			}
		}
	}
	else
	{
		this->arena = 0;
	}

	UTIL_PTR_LIST_FOREACH(update_characters, Character, character)
	{
		character->arena = this->arena;

		if (!this->arena)
		{
			character->Warp(character->map->id, character->map->relog_x, character->map->relog_y);
		}
	}
}

bool Map::Load()
{
	char namebuf[6];

	if (this->id < 0)
	{
		return false;
	}

	std::string filename = this->world->config["MapDir"];
	std::sprintf(namebuf, "%05i", this->id);
	this->filename = filename;
	filename.append(namebuf);
	filename.append(".emf");

	safe_fail_filename = filename.c_str();

	std::FILE *fh = std::fopen(filename.c_str(), "rb");

	if (!fh)
	{
		Console::Err("Could not load file: %s", filename.c_str());
		return false;
	}

	SAFE_SEEK(fh, 0x03, SEEK_SET);
	SAFE_READ(this->rid, sizeof(char), 4, fh);

	char buf[12];
	int outersize;
	int innersize;

	SAFE_SEEK(fh, 0x1F, SEEK_SET);
	SAFE_READ(buf, sizeof(char), 1, fh);
//this->effect = PacketProcessor::Number(buf[0])== 1;//apollo effect?
	this->pk = PacketProcessor::Number(buf[0]) == 3;

	SAFE_SEEK(fh, 0x25, SEEK_SET);
	SAFE_READ(buf, sizeof(char), 2, fh);
	this->width = PacketProcessor::Number(buf[0]) + 1;
	this->height = PacketProcessor::Number(buf[1]) + 1;

	this->tiles.resize(height);
	for (int i = 0; i < height; ++i)
	{
		this->tiles[i] = new PtrVector<Map_Tile>;
		this->tiles[i]->resize(width);
		for (int ii = 0; ii < width; ++ii)
		{
			this->tiles[i]->at(ii) = new Map_Tile;
		}
	}

	SAFE_SEEK(fh, 0x2A, SEEK_SET);
	SAFE_READ(buf, sizeof(char), 3, fh);
	this->scroll = PacketProcessor::Number(buf[0]);
	this->relog_x = PacketProcessor::Number(buf[1]);
	this->relog_y = PacketProcessor::Number(buf[2]);

	SAFE_SEEK(fh, 0x2E, SEEK_SET);
	SAFE_READ(buf, sizeof(char), 1, fh);
	outersize = PacketProcessor::Number(buf[0]);
	if (outersize)
	{
		SAFE_SEEK(fh, 8 * outersize, SEEK_CUR);
	}

	SAFE_READ(buf, sizeof(char), 1, fh);
	outersize = PacketProcessor::Number(buf[0]);
	if (outersize)
	{
		SAFE_SEEK(fh, 4 * outersize, SEEK_CUR);
	}

	SAFE_READ(buf, sizeof(char), 1, fh);
	outersize = PacketProcessor::Number(buf[0]);
	if (outersize)
	{
		SAFE_SEEK(fh, 12 * outersize, SEEK_CUR);
	}

	SAFE_READ(buf, sizeof(char), 1, fh);
	outersize = PacketProcessor::Number(buf[0]);
	for (int i = 0; i < outersize; ++i)
	{
		SAFE_READ(buf, sizeof(char), 2, fh);
		unsigned char yloc = PacketProcessor::Number(buf[0]);
		innersize = PacketProcessor::Number(buf[1]);
		for (int ii = 0; ii < innersize; ++ii)
		{
			Map_Tile *newtile(new Map_Tile);
			SAFE_READ(buf, sizeof(char), 2, fh);
			unsigned char xloc = PacketProcessor::Number(buf[0]);
			unsigned char spec = PacketProcessor::Number(buf[1]);
			newtile->tilespec = static_cast<Map_Tile::TileSpec>(spec);

			if (spec == Map_Tile::Chest)
			{

				Map_Chest *chest = new Map_Chest;
				chest->maxchest = static_cast<int>(this->world->config["MaxChest"]);
				chest->chestslots = static_cast<int>(this->world->config["ChestSlots"]);
				chest->x = xloc;
				chest->y = yloc;
				chest->slots = 0;
this->chests.push_back(chest); chest->Release();
			}
			try
			{
				this->tiles.at(yloc)->at(xloc) = newtile;
			}
			catch (...)
			{
				std::fclose(fh);
				safe_fail(__LINE__);
				return false;
			}
		}
	}

	SAFE_READ(buf, sizeof(char), 1, fh);
	outersize = PacketProcessor::Number(buf[0]);
	for (int i = 0; i < outersize; ++i)
	{
		SAFE_READ(buf, sizeof(char), 2, fh);
		unsigned char yloc = PacketProcessor::Number(buf[0]);
		innersize = PacketProcessor::Number(buf[1]);
		for (int ii = 0; ii < innersize; ++ii)
		{
			Map_Warp *newwarp(new Map_Warp);
			SAFE_READ(buf, sizeof(char), 8, fh);
			unsigned char xloc = PacketProcessor::Number(buf[0]);
			newwarp->map = PacketProcessor::Number(buf[1], buf[2]);
			newwarp->x = PacketProcessor::Number(buf[3]);
			newwarp->y = PacketProcessor::Number(buf[4]);
			newwarp->levelreq = PacketProcessor::Number(buf[5]);
			newwarp->spec = static_cast<Map_Warp::WarpSpec>(PacketProcessor::Number(buf[6], buf[7]));

			try
			{
				this->tiles.at(yloc)->at(xloc)->warp = newwarp;
			}
			catch (...)
			{
				std::fclose(fh);
				safe_fail(__LINE__);
				return false;
			}
		}
	}

	SAFE_SEEK(fh, 0x2E, SEEK_SET);
	SAFE_READ(buf, sizeof(char), 1, fh);
	outersize = PacketProcessor::Number(buf[0]);
	int index = 0;
	for (int i = 0; i < outersize; ++i)
	{
		SAFE_READ(buf, sizeof(char), 8, fh);
		unsigned char x = PacketProcessor::Number(buf[0]);
		unsigned char y = PacketProcessor::Number(buf[1]);
		short npc_id = PacketProcessor::Number(buf[2], buf[3]);
		unsigned char spawntype = PacketProcessor::Number(buf[4]);
		short spawntime = PacketProcessor::Number(buf[5], buf[6]);
		unsigned char amount = PacketProcessor::Number(buf[7]);

		if (npc_id != this->world->enf->Get(npc_id)->id)
		{
			Console::Wrn("An NPC spawn on map %i uses a non-existent NPC (#%i at %ix%i)", this->id, npc_id, x, y);
		}

		for (int ii = 0; ii < amount; ++ii)
		{
			if (x > this->width || y > this->height)
			{
				Console::Wrn("An NPC spawn on map %i is outside of map bounds (%s at %ix%i)", this->id, this->world->enf->Get(npc_id)->name.c_str(), x, y);
				continue;
			}

			NPC *newnpc = new NPC(this, npc_id, x, y, spawntype, spawntime, index++);
			this->npcs.push_back(newnpc);

			newnpc->Spawn();
		}
	}

	SAFE_READ(buf, sizeof(char), 1, fh);
	outersize = PacketProcessor::Number(buf[0]);
	if (outersize)
	{
		SAFE_SEEK(fh, 4 * outersize, SEEK_CUR);
	}

	SAFE_READ(buf, sizeof(char), 1, fh);
	outersize = PacketProcessor::Number(buf[0]);
	for (int i = 0; i < outersize; ++i)
	{
		SAFE_READ(buf, sizeof(char), 12, fh);
		unsigned char x = PacketProcessor::Number(buf[0]);
		unsigned char y = PacketProcessor::Number(buf[1]);
		short slot = PacketProcessor::Number(buf[4]);
		short itemid = PacketProcessor::Number(buf[5], buf[6]);
		short time = PacketProcessor::Number(buf[7], buf[8]);
		int amount = PacketProcessor::Number(buf[9], buf[10], buf[11]);

		if (itemid != this->world->eif->Get(itemid)->id)
		{
			Console::Wrn("A chest spawn on map %i uses a non-existent item (#%i at %ix%i)", this->id, itemid, x, y);
		}

		UTIL_PTR_VECTOR_FOREACH(this->chests, Map_Chest, chest)
		{
			if (chest->x == x && chest->y == y)
			{
				Map_Chest_Item *item(new Map_Chest_Item);
				Map_Chest_Spawn *spawn(new Map_Chest_Spawn);

				item->id = itemid;
				item->amount = amount;

				spawn->slot = slot+1;
				spawn->time = time;
				spawn->last_taken = Timer::GetTime();
				spawn->item = item;

				chest->spawns.push_back(spawn);
				spawn->Release();
				chest->slots = std::max(chest->slots, slot+1);
				goto skip_warning;
			}
		}
		Console::Wrn("A chest spawn on map %i points to a non-chest (%s x%i at %ix%i)", this->id, this->world->eif->Get(itemid)->name.c_str(), amount, x, y);
		skip_warning:
		;
	}

	SAFE_SEEK(fh, 0x00, SEEK_END);
	this->filesize = std::ftell(fh);

	std::fclose(fh);

	this->exists = true;

	return true;
}

void Map::Unload()
{
	this->exists = false;

	this->chests.clear();

	UTIL_PTR_VECTOR_FOREACH(this->npcs, NPC, npc)
	{
		UTIL_PTR_LIST_FOREACH(npc->damagelist, NPC_Opponent, opponent)
		{
			erase_first(opponent->attacker->unregister_npc, *npc);
		}
	}

	this->npcs.clear();
}

int Map::GenerateItemID()
{
	int lowest_free_id = 1;
	restart_loop:
	UTIL_PTR_LIST_FOREACH(this->items, Map_Item, item)
	{
		if (item->uid == lowest_free_id)
		{
			lowest_free_id = item->uid + 1;
			goto restart_loop;
		}
	}
	return lowest_free_id;
}

unsigned char Map::GenerateNPCIndex()
{
	unsigned char lowest_free_id = 1;
	restart_loop:
	UTIL_PTR_VECTOR_FOREACH(this->npcs, NPC, npc)
	{
		if (npc->index == lowest_free_id)
		{
			lowest_free_id = npc->index + 1;
			goto restart_loop;
		}
	}
	return lowest_free_id;
}

void Map::Enter(Character *character, WarpAnimation animation)
{

	PacketBuilder builder;
	this->characters.push_back(character);
	character->map = this;

	builder.SetID(PACKET_PLAYERS, PACKET_AGREE);

	builder.AddByte(255);
	builder.AddBreakString(character->name);
	builder.AddShort(character->player->id);
	builder.AddShort(character->mapid);
	builder.AddShort(character->x);
	builder.AddShort(character->y);
	builder.AddChar(character->direction);
	builder.AddChar(character->clas); // character class
	builder.AddString(character->PaddedGuildTag());
	builder.AddChar(character->level);
	builder.AddChar(character->gender);
	builder.AddChar(character->hairstyle);
	builder.AddChar(character->haircolor);
	builder.AddChar(character->race);
	builder.AddShort(character->maxhp);
	builder.AddShort(character->hp);
	builder.AddShort(character->maxtp);
	builder.AddShort(character->tp);
	// equipment
	builder.AddShort(this->world->eif->Get(character->paperdoll[Character::Boots])->dollgraphic);
	builder.AddShort(0); // ??
	builder.AddShort(0); // ??
	builder.AddShort(0); // ??
	builder.AddShort(this->world->eif->Get(character->paperdoll[Character::Armor])->dollgraphic);
	builder.AddShort(0); // ??
	builder.AddShort(this->world->eif->Get(character->paperdoll[Character::Hat])->dollgraphic);
	builder.AddShort(this->world->eif->Get(character->paperdoll[Character::Shield])->dollgraphic);
	builder.AddShort(this->world->eif->Get(character->paperdoll[Character::Weapon])->dollgraphic);
	builder.AddChar(character->sitting);
	builder.AddChar(character->hidden);
	builder.AddChar(animation);
	builder.AddByte(255);
	builder.AddChar(1); // 0 = NPC, 1 = player

		UTIL_PTR_LIST_FOREACH(this->characters, Character, checkcharacter)
	{

		if (*checkcharacter == character || !character->InRange(*checkcharacter))
		{
			continue;
		}
		checkcharacter->player->client->SendBuilder(builder);
}
}
void Map::Leave(Character *character, WarpAnimation animation, bool silent)
{
	if (!silent)
	{
		PacketBuilder builder;

		builder.SetID(PACKET_CLOTHES, PACKET_REMOVE);
		builder.AddShort(character->player->id);
		if (animation != WARP_ANIMATION_NONE)
		{
			builder.AddChar(animation);
		}

		UTIL_PTR_LIST_FOREACH(this->characters, Character, checkcharacter)
		{
			if (*checkcharacter == character || !character->InRange(*checkcharacter))
			{
				continue;
			}

			checkcharacter->player->client->SendBuilder(builder);
		}
	}

	erase_first(this->characters, character);
	character->map = 0;

}

void Map::Msg(Character *from, std::string message, bool echo)
{
	message = util::text_cap(message, static_cast<int>(this->world->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from->name) + "  "));

	PacketBuilder builder;

	builder.SetID(PACKET_TALK, PACKET_PLAYER);
	builder.AddShort(from->player->id);
	builder.AddString(message);

	UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
	{
		if ((!echo && *character == from) || !from->InRange(*character))
		{
			continue;
		}

		character->player->client->SendBuilder(builder);
	}
}

bool Map::Walk(Character *from, Direction direction, bool admin)
{
	PacketBuilder builder;
	int seedistance = this->world->config["SeeDistance"];

	unsigned char target_x = from->x;
	unsigned char target_y = from->y;

	switch (direction)
	{
		case DIRECTION_UP:
			target_y -= 1;

			if (target_y > from->y)
			{
				return false;
			}

			break;

		case DIRECTION_RIGHT:
			target_x += 1;

			if (target_x < from->x)
			{
				return false;
			}

			break;

		case DIRECTION_DOWN:
			target_y += 1;

			if (target_x < from->x)
			{
				return false;
			}

			break;

		case DIRECTION_LEFT:
			target_x -= 1;

			if (target_x > from->x)
			{
				return false;
			}

			break;
	}
      PacketBuilder reply;

// if you dont have a god mode remove && from->invincible == false) and the first (
       if((from->map->GetSpec(target_x, target_y) == Map_Tile::Spikes1 || from->map->GetSpec(target_x, target_y) == Map_Tile::Spikes2 || from->map->GetSpec(target_x, target_y) == Map_Tile::Spikes3)&& from->invincible == false)
          {
           //PacketBuilder builder;
           int amount = util::rand(2, static_cast<int>(this->world->config["SpikeDamage"]));
           UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
           {
            int limitamount = std::min(amount, int(from->hp));

             if (this->world->config["LimitDamage"])
                {
                 amount = limitamount;
                }

                from->hp -= limitamount;

                PacketBuilder builder(PACKET_CLOTHES, PACKET_REPLY);
                builder.AddShort(0);
                builder.AddShort(from->player->id);
                builder.AddThree(amount);
                builder.AddChar(from->direction);
                builder.AddChar(int(double(from->hp) / double(from->maxhp) * 100.0));
                builder.AddChar(from->hp == 0);

                if(from->InRange(*character))
                  {
                  character->player->client->SendBuilder(builder);
                  }

          if(from->hp == 0)
           {
           int sm = from->SpawnMap();
           int sx = from->SpawnX();
           int sy =  from->SpawnY();

           from->PetTransfer();//if you dont have a pet system remove this line
           from->Warp(sm, sx, sy, WARP_ANIMATION_ADMIN);
           from->PetTransfer();//if you dont have a pet system remove this line
           from->hp = from->maxhp;

        if(from->x == sx && from->y == sy)
           {

        builder.Reset();
        builder.SetID(PACKET_RECOVER, PACKET_PLAYER);
        builder.AddShort(from->hp);
        builder.AddInt(from->exp);
        builder.AddShort(from->tp);
        from->player->client->SendBuilder(builder);

        }
         break;
    }
           builder.Reset();
           builder.SetID(PACKET_RECOVER, PACKET_PLAYER);
           builder.AddShort(from->hp);
           builder.AddInt(from->exp);
           builder.AddShort(from->tp);

            from->player->client->SendBuilder(builder);

           }
        }

    int uid = 1;
    Map_Item *item = this->GetItem(uid);

    if(from->paperdoll[Character::Boots] == 125 )
			{
            if (item)
			{
    int distance = util::path_length(item->x, item->y, from->x, from->y);

    if (distance < 2 && item->owner == from->player->id)
            {

            from->AddItem(item->id, item->amount);

            reply.SetID(PACKET_ITEM, PACKET_GET);
            reply.AddShort(uid);
            reply.AddShort(item->id);
            reply.AddThree(item->amount);
            reply.AddChar(from->weight);
            reply.AddChar(from->maxweight);
            from->player->client->SendBuilder(reply);

            this->DelItem(item, from);

			}
         }
      }

if (this->id == 435 && this->GetSpec(target_x, target_y) == Map_Tile::Unknown3)
				{
reply.SetID(PACKET_PING, PACKET_ACCEPT);
reply.AddByte(255);
reply.AddString(static_cast<std::string>(this->world->message_config["book"]));
from->player->client->SendBuilder(reply);
			}
if (this->id == 438 && this->GetSpec(target_x, target_y) == Map_Tile::Unknown3)
				{
reply.SetID(PACKET_PING, PACKET_ACCEPT);
reply.AddByte(255);
reply.AddString(static_cast<std::string>(this->world->message_config["book1"]));
from->player->client->SendBuilder(reply);
			}
			if (this->id == 439 && this->GetSpec(target_x, target_y) == Map_Tile::Unknown3)
				{
reply.SetID(PACKET_PING, PACKET_ACCEPT);
reply.AddByte(255);
reply.AddString(static_cast<std::string>(this->world->message_config["book2"]));
from->player->client->SendBuilder(reply);
			}
			if (this->id == 440 && this->GetSpec(target_x, target_y) == Map_Tile::Unknown3)
				{
reply.SetID(PACKET_PING, PACKET_ACCEPT);
reply.AddByte(255);
reply.AddString(static_cast<std::string>(this->world->message_config["book3"]));
from->player->client->SendBuilder(reply);
			}

	if (!admin && !this->Walkable(target_x, target_y))
	{
		return false;
	}

	Map_Warp *warp;
	if (!admin && (warp = this->GetWarp(target_x, target_y)))
	{
		if (from->level >= warp->levelreq && (warp->spec == Map_Warp::NoDoor || warp->open))
		{

        if (from->race == SKIN_ORC && this->id == 426)
	{
    from->hairstyle = 14;
    from->race = SKIN_WHITE;
        }
          if (from->race == SKIN_ORC && this->id == 425)
	{
    from->hairstyle = 13;
    from->race = SKIN_WHITE;
        }
        from->PetTransfer();
			from->Warp(warp->map, warp->x, warp->y);
		 from->PetTransfer();
		}

		return false;
	}

	from->direction = direction;

	HOOK_BEGIN(CharacterEvent, this->world->hookmanager, "character/walk")
		e->character = from;
		e->target_map = this;
		e->target_mapid = this->id;
		e->target_x = target_x;
		e->target_y = target_y;
		if (HOOK_CALL()) return false;
	HOOK_END()

	from->x = target_x;
	from->y = target_y;

	int newx;
	int newy;
	int oldx;
	int oldy;

	std::vector<std::pair<int, int> > newcoords;
	std::vector<std::pair<int, int> > oldcoords;

	PtrVector<Character> newchars;
	PtrVector<Character> oldchars;
	PtrVector<NPC> newnpcs;
	PtrVector<NPC> oldnpcs;
	PtrVector<Map_Item> newitems;

	switch (direction)
	{
		case DIRECTION_UP:
			for (int i = -seedistance; i <= seedistance; ++i)
			{
				newy = from->y - seedistance + std::abs(i);
				newx = from->x + i;
				oldy = from->y + seedistance + 1 - std::abs(i);
				oldx = from->x + i;

				newcoords.push_back(std::make_pair(newx, newy));
				oldcoords.push_back(std::make_pair(oldx, oldy));
			}
			break;

		case DIRECTION_RIGHT:
			for (int i = -seedistance; i <= seedistance; ++i)
			{
				newx = from->x + seedistance - std::abs(i);
				newy = from->y + i;
				oldx = from->x - seedistance - 1 + std::abs(i);
				oldy = from->y + i;

				newcoords.push_back(std::make_pair(newx, newy));
				oldcoords.push_back(std::make_pair(oldx, oldy));
			}
			break;

		case DIRECTION_DOWN:
			for (int i = -seedistance; i <= seedistance; ++i)
			{
				newy = from->y + seedistance - std::abs(i);
				newx = from->x + i;
				oldy = from->y - seedistance - 1 + std::abs(i);
				oldx = from->x + i;

				newcoords.push_back(std::make_pair(newx, newy));
				oldcoords.push_back(std::make_pair(oldx, oldy));
			}
			break;

		case DIRECTION_LEFT:
			for (int i = -seedistance; i <= seedistance; ++i)
			{
				newx = from->x - seedistance + std::abs(i);
				newy = from->y + i;
				oldx = from->x + seedistance + 1 - std::abs(i);
				oldy = from->y + i;

				newcoords.push_back(std::make_pair(newx, newy));
				oldcoords.push_back(std::make_pair(oldx, oldy));
			}
			break;

	}

	UTIL_PTR_LIST_FOREACH(this->characters, Character, checkchar)
	{
		if (*checkchar == from)
		{
			continue;
		}

		for (std::size_t i = 0; i < oldcoords.size(); ++i)
		{
			if (checkchar->x == oldcoords[i].first && checkchar->y == oldcoords[i].second)
			{
				oldchars.push_back(*checkchar);
			}
			else if (checkchar->x == newcoords[i].first && checkchar->y == newcoords[i].second)
			{
				newchars.push_back(*checkchar);
			}
		}
	}

	UTIL_PTR_VECTOR_FOREACH(this->npcs, NPC, checknpc)
	{
		if (!checknpc->alive)
		{
			continue;
		}

		for (std::size_t i = 0; i < oldcoords.size(); ++i)
		{
			if (checknpc->x == oldcoords[i].first && checknpc->y == oldcoords[i].second)
			{
				oldnpcs.push_back(*checknpc);
			}
			else if (checknpc->x == newcoords[i].first && checknpc->y == newcoords[i].second)
			{
				newnpcs.push_back(*checknpc);
			}
		}
	}

	UTIL_PTR_LIST_FOREACH(this->items, Map_Item, checkitem)
	{
		for (std::size_t i = 0; i < oldcoords.size(); ++i)
		{
			if (checkitem->x == newcoords[i].first && checkitem->y == newcoords[i].second)
			{
				newitems.push_back(*checkitem);
			}
		}
	}

 Quest *temp_quest = 0;
	State *state = 0;
	UTIL_PTR_LIST_FOREACH(from->quests, Character_Quest, quest)
	{
	    temp_quest = this->world->GetQuest(quest->id);
	    if (!temp_quest) continue;

	    state = temp_quest->GetState(quest->state);
	    if (!state) continue;

	    UTIL_PTR_VECTOR_FOREACH(state->rules, Rule, rule)
	    {
	        if ((rule->name.compare("entercoord") == 0 || rule->name.compare("leavecoord") == 0)
                && ((int)(*rule->args[0])) == from->mapid && ((int)(*rule->args[1])) == from->x && ((int)(*rule->args[2])) == from->y)
	        {
                    quest->state = rule->goto_state;
                    from->PerformQuestActions(quest->id);
                    break;
                }
            }
        }


	builder.SetID(PACKET_CLOTHES, PACKET_REMOVE);
	builder.AddShort(from->player->id);

	UTIL_PTR_VECTOR_FOREACH(oldchars, Character, character)
	{
		PacketBuilder rbuilder;
		rbuilder.SetID(PACKET_CLOTHES, PACKET_REMOVE);
		rbuilder.AddShort(character->player->id);

		character->player->client->SendBuilder(builder);
		from->player->client->SendBuilder(rbuilder);
	}

	builder.Reset();

	builder.SetID(PACKET_PLAYERS, PACKET_AGREE);
	builder.AddByte(255);
	builder.AddBreakString(from->name);
	builder.AddShort(from->player->id);
	builder.AddShort(from->mapid);
	builder.AddShort(from->x);
	builder.AddShort(from->y);
	builder.AddChar(from->direction);
	builder.AddChar(from->clas); // character class
	builder.AddString(from->PaddedGuildTag());
	builder.AddChar(from->level);
	builder.AddChar(from->gender);
	builder.AddChar(from->hairstyle);
	builder.AddChar(from->haircolor);
	builder.AddChar(from->race);
	builder.AddShort(from->maxhp);
	builder.AddShort(from->hp);
	builder.AddShort(from->maxtp);
	builder.AddShort(from->tp);
	// equipment
	builder.AddShort(this->world->eif->Get(from->paperdoll[Character::Boots])->dollgraphic);
	builder.AddShort(0); // ??
	builder.AddShort(0); // ??
	builder.AddShort(0); // ??
	builder.AddShort(this->world->eif->Get(from->paperdoll[Character::Armor])->dollgraphic);
	builder.AddShort(0); // ??
	builder.AddShort(this->world->eif->Get(from->paperdoll[Character::Hat])->dollgraphic);
	builder.AddShort(this->world->eif->Get(from->paperdoll[Character::Shield])->dollgraphic);
	builder.AddShort(this->world->eif->Get(from->paperdoll[Character::Weapon])->dollgraphic);
	builder.AddChar(from->sitting);
	builder.AddChar(from->hidden);
	builder.AddByte(255);
	builder.AddChar(1); // 0 = NPC, 1 = player

	UTIL_PTR_VECTOR_FOREACH(newchars, Character, character)
	{
		PacketBuilder rbuilder;
		rbuilder.SetID(PACKET_PLAYERS, PACKET_AGREE);
		rbuilder.AddByte(255);
		rbuilder.AddBreakString(character->name);
		rbuilder.AddShort(character->player->id);
		rbuilder.AddShort(character->mapid);
		rbuilder.AddShort(character->x);
		rbuilder.AddShort(character->y);
		rbuilder.AddChar(character->direction);
		rbuilder.AddChar(character->clas); // ?
		rbuilder.AddString(character->PaddedGuildTag());
		rbuilder.AddChar(character->level);
		rbuilder.AddChar(character->gender);
		rbuilder.AddChar(character->hairstyle);
		rbuilder.AddChar(character->haircolor);
		rbuilder.AddChar(character->race);
		rbuilder.AddShort(character->maxhp);
		rbuilder.AddShort(character->hp);
		rbuilder.AddShort(character->maxtp);
		rbuilder.AddShort(character->tp);
		// equipment
		rbuilder.AddShort(this->world->eif->Get(character->paperdoll[Character::Boots])->dollgraphic);
		rbuilder.AddShort(0); // ??
		rbuilder.AddShort(0); // ??
		rbuilder.AddShort(0); // ??
		rbuilder.AddShort(this->world->eif->Get(character->paperdoll[Character::Armor])->dollgraphic);
		rbuilder.AddShort(0); // ??
		rbuilder.AddShort(this->world->eif->Get(character->paperdoll[Character::Hat])->dollgraphic);
		rbuilder.AddShort(this->world->eif->Get(character->paperdoll[Character::Shield])->dollgraphic);
		rbuilder.AddShort(this->world->eif->Get(character->paperdoll[Character::Weapon])->dollgraphic);
		rbuilder.AddChar(character->sitting);
		rbuilder.AddChar(character->hidden);
		rbuilder.AddByte(255);
		rbuilder.AddChar(1); // 0 = NPC, 1 = player

		character->player->client->SendBuilder(builder);
		from->player->client->SendBuilder(rbuilder);
	}

	builder.Reset();

	builder.SetID(PACKET_WALK, PACKET_PLAYER);
	builder.AddShort(from->player->id);
	builder.AddChar(direction);
	builder.AddChar(from->x);
	builder.AddChar(from->y);

	UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
	{
		if (*character == from || !from->InRange(*character))
		{
			continue;
		}

		character->player->client->SendBuilder(builder);
	}

	builder.Reset();

	builder.SetID(PACKET_WALK, PACKET_REPLY);
	builder.AddByte(255);
	builder.AddByte(255);
	UTIL_PTR_VECTOR_FOREACH(newitems, Map_Item, item)
	{
		builder.AddShort(item->uid);
		builder.AddShort(item->id);
		builder.AddChar(item->x);
		builder.AddChar(item->y);
		builder.AddThree(item->amount);
	}
	from->player->client->SendBuilder(builder);

	builder.SetID(PACKET_APPEAR, PACKET_REPLY);
	UTIL_PTR_VECTOR_FOREACH(newnpcs, NPC, npc)
	{
		builder.Reset();
		builder.AddChar(0);
		builder.AddByte(255);
		builder.AddChar(npc->index);
		builder.AddShort(npc->id);
		builder.AddChar(npc->x);
		builder.AddChar(npc->y);
		builder.AddChar(npc->direction);

		from->player->client->SendBuilder(builder);
	}

	UTIL_PTR_VECTOR_FOREACH(oldnpcs, NPC, npc)
	{
		npc->RemoveFromView(from);
	}

	return true;
}

bool Map::Walk(NPC *from, Direction direction)
{
 PacketBuilder builder;
	int seedistance = this->world->config["SeeDistance"];

	unsigned char target_x = from->x;
	unsigned char target_y = from->y;

	switch (direction)
	{
		case DIRECTION_UP:
			target_y -= 1;

			if (target_y > from->y)
			{
				return false;
			}

			break;

		case DIRECTION_RIGHT:
			target_x += 1;

			if (target_x < from->x)
			{
				return false;
			}

			break;

		case DIRECTION_DOWN:
			target_y += 1;

			if (target_x < from->x)
			{
				return false;
			}

			break;

		case DIRECTION_LEFT:
			target_x -= 1;

			if (target_x > from->x)
			{
				return false;
			}

			break;
	}
if (from->pet && from->Data()->type == ENF::Pet && (!this->Walkable(target_x, target_y, Map_Tile::Wall)))
{
return false;
}

	if (!from->pet && !from->Data()->type != ENF::Pet && (!this->Walkable(target_x, target_y, true)) || this->Occupied(target_x, target_y, Map::PlayerAndNPC))//need to test removeing pets and leave above code only
	{
		return false;
	}

	from->x = target_x;
	from->y = target_y;

	int newx;
	int newy;
	int oldx;
	int oldy;

	std::vector<std::pair<int, int> > newcoords;
	std::vector<std::pair<int, int> > oldcoords;

	PtrVector<Character> newchars;
	PtrVector<Character> oldchars;

	switch (direction)
	{
		case DIRECTION_UP:
			for (int i = -seedistance; i <= seedistance; ++i)
			{
				newy = from->y - seedistance + std::abs(i);
				newx = from->x + i;
				oldy = from->y + seedistance + 1 - std::abs(i);
				oldx = from->x + i;

				newcoords.push_back(std::make_pair(newx, newy));
				oldcoords.push_back(std::make_pair(oldx, oldy));
			}
			break;

		case DIRECTION_RIGHT:
			for (int i = -seedistance; i <= seedistance; ++i)
			{
				newx = from->x + seedistance - std::abs(i);
				newy = from->y + i;
				oldx = from->x - seedistance - 1 + std::abs(i);
				oldy = from->y + i;

				newcoords.push_back(std::make_pair(newx, newy));
				oldcoords.push_back(std::make_pair(oldx, oldy));
			}
			break;

		case DIRECTION_DOWN:
			for (int i = -seedistance; i <= seedistance; ++i)
			{
				newy = from->y + seedistance - std::abs(i);
				newx = from->x + i;
				oldy = from->y - seedistance - 1 + std::abs(i);
				oldx = from->x + i;

				newcoords.push_back(std::make_pair(newx, newy));
				oldcoords.push_back(std::make_pair(oldx, oldy));
			}
			break;

		case DIRECTION_LEFT:
			for (int i = -seedistance; i <= seedistance; ++i)
			{
				newx = from->x - seedistance + std::abs(i);
				newy = from->y + i;
				oldx = from->x + seedistance + 1 - std::abs(i);
				oldy = from->y + i;

				newcoords.push_back(std::make_pair(newx, newy));
				oldcoords.push_back(std::make_pair(oldx, oldy));
			}
			break;

	}

	from->direction = direction;

	UTIL_PTR_LIST_FOREACH(this->characters, Character, checkchar)
	{
		for (std::size_t i = 0; i < oldcoords.size(); ++i)
		{
			if (checkchar->x == oldcoords[i].first && checkchar->y == oldcoords[i].second)
			{
				oldchars.push_back(*checkchar);
			}
			else if (checkchar->x == newcoords[i].first && checkchar->y == newcoords[i].second)
			{
				newchars.push_back(*checkchar);
			}
		}
	}

	builder.SetID(PACKET_APPEAR, PACKET_REPLY);
	builder.AddChar(0);
	builder.AddByte(255);
	builder.AddChar(from->index);
	builder.AddShort(from->id);
	builder.AddChar(from->x);
	builder.AddChar(from->y);
	builder.AddChar(from->direction);

	UTIL_PTR_VECTOR_FOREACH(newchars, Character, character)
	{
		character->player->client->SendBuilder(builder);
	}

	builder.Reset();

	builder.SetID(PACKET_NPC, PACKET_PLAYER);
	builder.AddChar(from->index);
	builder.AddChar(from->x);
	builder.AddChar(from->y);
	builder.AddChar(from->direction);
	builder.AddByte(255);
	builder.AddByte(255);
	builder.AddByte(255);

	UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
	{
		if (!character->InRange(from))
		{
			continue;
		}

		character->player->client->SendBuilder(builder);
	}

	UTIL_PTR_VECTOR_FOREACH(oldchars, Character, character)
	{
		from->RemoveFromView(*character);
	}

	return true;
}

void Map::Attack(Character *from, Direction direction)
{
	PacketBuilder builder;

	from->direction = direction;

	if (this->id == 426)
	{

    int target_x = from->x;
	int target_y = from->y;

	switch (from->direction)
	{
		case DIRECTION_UP:
			target_y -= 1;
			break;

		case DIRECTION_RIGHT:
			target_x += 1;
			break;

		case DIRECTION_DOWN:
			target_y += 1;
			break;

		case DIRECTION_LEFT:
			target_x -= 1;
			break;
	}

	  UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
	{
		Character *character_ptr = *character;
		character_ptr->AddRef();

UTIL_PTR_VECTOR_FOREACH(this->npcs, NPC, npc)
            {
               	if (from->race != SKIN_ORC)
	{
                if (npc->Data()->id == 2 && npc->alive && npc->x == target_x && npc->y == target_y)
                {
			    //std::string msg(from->name + " HAS BEEN INFECTED ");
this->world->ServerMsg(from->name + " HAS BEEN INFECTED ");
from->hairstyle = 0;
from->race = SKIN_ORC;
from->Refresh();
			}
		}
            }
		if (from->race == SKIN_ORC)
	{
		if (character_ptr->x == target_x && character_ptr->y == target_y && character->race != SKIN_ORC)
		{
int item = 1;
int amount = 2000;
if (from->AddItem(item, amount))
            {
    PacketBuilder builder(PACKET_ITEM, PACKET_GET);
    builder.AddShort(0); // UID
    builder.AddShort(item);
    builder.AddThree(amount);
    builder.AddChar(from->weight);
    builder.AddChar(from->maxweight);
    from->player->client->SendBuilder(builder);
            }

bool stats_updated = false;
from->exp += 1000;
stats_updated = true;
if (stats_updated)
    {
 bool level_up = false;
 while (from->level < static_cast<int>(this->world->config["MaxLevel"]) && from->exp >= this->world->exp_table[from->level+1])
        {
    level_up = true;
    ++from->level;
    from->statpoints += static_cast<int>(this->world->config["StatPerLevel"]);
    from->skillpoints += static_cast<int>(this->world->config["SkillPerLevel"]);
    from->CalculateStats();
        }

    PacketBuilder builder(PACKET_RECOVER, PACKET_REPLY);
    builder.AddInt(from->exp);
    builder.AddShort(from->karma);
    builder.AddChar(level_up ? from->level : 0);
    from->player->client->SendBuilder(builder);
    }
this->world->ServerMsg(character_ptr->name + " has been infected by " + from->name);

			character_ptr->hairstyle = 0;
			character_ptr->race = SKIN_ORC;
			character_ptr->Warp(426, 1, 1);
			character_ptr->Release();
			break;
		}
	}
		character_ptr->Release();
	}
	}

	if (from->arena)
	{
    from->arena->Attack(from, direction);

	}

	if (this->pk || (this->world->config["GlobalPK"] && !this->world->PKExcept(this->id)))
	{
		if (this->AttackPK(from, direction))
		{
			return;
		}
	}

	builder.SetID(PACKET_ATTACK, PACKET_PLAYER);
	builder.AddShort(from->player->id);
	builder.AddChar(direction);

	UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
	{
		if (*character == from || !from->InRange(*character))
		{
			continue;
		}

		character->player->client->SendBuilder(builder);
	}

	int target_x = from->x;
	int target_y = from->y;

	int range = 1;

if (this->world->eif->Get(from->paperdoll[Character::Weapon])->subtype == EIF::Ranged)
	{
		range = static_cast<int>(this->world->config["RangedDistance"]);
	}

	for (int i = 0; i < range; ++i)
	{
		switch (from->direction)
		{
			case DIRECTION_UP:
				target_y -= 1;
				break;

			case DIRECTION_RIGHT:
				target_x += 1;
				break;

			case DIRECTION_DOWN:
				target_y += 1;
				break;

			case DIRECTION_LEFT:
				target_x -= 1;
				break;
		}

       	if (from->paperdoll[Character::Weapon] != 690 && !this->Walkable(target_x, target_y, true))
  {
   break;
  }

        UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
        {
            UTIL_PTR_VECTOR_FOREACH(this->npcs, NPC, npc)
            {

      int eff = util::rand(1, 32);// doesnt have to be a random u could give a specific effect id EX: int eff = 5;
      int dmg = util::rand(from->mindam, from->maxdam);
      int dist = util::path_length(target_x, target_y, npc->x, npc->y);

     if ((npc->Data()->type == ENF::Passive || npc->Data()->type == ENF::Aggressive ||
      from->admin > static_cast<int>(this->world->admin_config["killnpcs"])) && npc->alive &&
      dist < 4 && this->world->eif->Get(from->paperdoll[Character::Weapon])->aoe == 1 )
       {
            npc->Damage(from, dmg);
       }

      if ((npc->Data()->type == ENF::Passive || npc->Data()->type == ENF::Aggressive ||
      from->admin > static_cast<int>(this->world->admin_config["killnpcs"])) && npc->alive &&
      dist < 4 && this->world->eif->Get(from->paperdoll[Character::Weapon])->aoe == 2 )
       {
            npc->Effect(from, eff, dmg);// if you dont have ananas effect or dont want effect remove this line
            npc->Damage(from, dmg);
       }

                if ((npc->pet || npc->Data()->type == ENF::Pet || npc->Data()->type == ENF::Unknown3 || npc->Data()->type == ENF::Unknown4 || npc->Data()->type == ENF::Passive || npc->Data()->type == ENF::Aggressive || from->admin > static_cast<int>(this->world->admin_config["killnpcs"]))
                 && npc->alive && npc->x == target_x && npc->y == target_y)
                {

int itemid, effectid;
for(int i = 0 ; i < static_cast<int>(this->world->effects_config["WAmount"]) ; i++){
itemid = static_cast<int>(this->world->effects_config[util::to_string(i+1) + ".ItemID"]);
effectid = static_cast<int>(this->world->effects_config[util::to_string(i+1) + ".EffectID"]);
    if(from->paperdoll[Character::Weapon] == itemid){
                npc->Effect(from, effectid, 0);
                    }
                }
                  if(from->clas == 9)
                    {

                        int amount = util::rand(from->mindam + 0, from->maxdam + 0);
                        double rand = util::rand(0.0, 1.0);
                        // Checks if target is facing you
                        bool critical = std::abs(int(npc->direction) - from->direction) != 2 || rand < static_cast<double>(this->world->config["CriticalRate"]);

                        std::tr1::unordered_map<std::string, double> formula_vars;

                        from->FormulaVars(formula_vars);
                        npc->FormulaVars(formula_vars, "target_");
                        formula_vars["modifier"] = this->world->config["MobRate"];
                        formula_vars["damage"] = amount;
                        formula_vars["critical"] = critical;

                        amount = rpn_eval(rpn_parse(this->world->formulas_config["damage"]), formula_vars);
                        double hit_rate = rpn_eval(rpn_parse(this->world->formulas_config["hit_rate"]), formula_vars);

                        if (rand > hit_rate)
                        {
                            amount = 0;
                        }

                        amount = std::max(amount, 0);

                        int limitamount = std::min(amount, int(npc->hp));

                        if (this->world->config["LimitDamage"])
                        {
                            amount = limitamount;
                        }

                        npc->Damage(from, amount);
                    }

                    else if(from->clas != 9)
                    {
                        int amount = util::rand(from->mindam, from->maxdam);
                        double rand = util::rand(0.0, 1.0);
                        // Checks if target is facing you
                        bool critical = std::abs(int(npc->direction) - from->direction) != 2 || rand < static_cast<double>(this->world->config["CriticalRate"]);

                        std::tr1::unordered_map<std::string, double> formula_vars;

                        from->FormulaVars(formula_vars);
                        npc->FormulaVars(formula_vars, "target_");
                        formula_vars["modifier"] = this->world->config["MobRate"];
                        formula_vars["damage"] = amount;
                        formula_vars["critical"] = critical;

                        amount = rpn_eval(rpn_parse(this->world->formulas_config["damage"]), formula_vars);
                        double hit_rate = rpn_eval(rpn_parse(this->world->formulas_config["hit_rate"]), formula_vars);

                        if (rand > hit_rate)
                        {
                            amount = 0;
                        }

                        amount = std::max(amount, 0);

                        int limitamount = std::min(amount, int(npc->hp));

                        if (this->world->config["LimitDamage"])
                        {
                            amount = limitamount;
                        }

                        npc->Damage(from, amount);

                        return;
                    }
                }
            }
        }
	}
}

void Map::AttackSpell(Character *from, int spellid, int targetid)
{
     ESF_Data *spell = this->world->esf->Get(spellid);
     if (!spell) return;

    if (this->pk || (static_cast<int>(this->world->config["GlobalPK"]) && !this->world->PKExcept(this->id)))
    {
        if (this->AttackPKSpell(from, spellid, targetid))
        {
            return;
        }
    }
    UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
    {
        UTIL_PTR_VECTOR_FOREACH(this->npcs, NPC, npc)
        {
          
            if (from->clas == 9)
            {
                if ((npc->pet || npc->Data()->type == ENF::Pet || npc->Data()->type == ENF::Unknown3 || npc->Data()->type == ENF::Unknown4 || npc->Data()->type == ENF::Passive || npc->Data()->type == ENF::Aggressive || from->admin > static_cast<int>(this->world->admin_config["killnpcs"]))
                && npc->alive)
                {
               
                    int amount = util::rand(spell->mindam + spl->level * 9999, spell->maxdam + spl->level * 9999);
                    //int amount = util::rand(from->mindam + 0, from->maxdam + 0);
                    npc->SpellDamage(from, amount, spellid, targetid);
                 }
         }

            else if (from->clas != 9)
            {
            if ((npc->pet || npc->Data()->type == ENF::Pet || npc->Data()->type == ENF::Unknown3 || npc->Data()->type == ENF::Unknown4 || npc->Data()->type == ENF::Passive || npc->Data()->type == ENF::Aggressive || from->admin > static_cast<int>(this->world->admin_config["killnpcs"]))
            && npc->alive && npc->index == targetid)
                {
                  
                         int amount = util::rand(spell->mindam , spell->maxdam);
                         //int amount = util::rand(from->mindam + 0, from->maxdam + 0);
                          npc->SpellDamage(from, amount, spellid, targetid);

                          return;                       
                        }
              }
         }
    }
}
bool Map::AttackPK(Character *from, Direction direction)
{
	int target_x = from->x;
	int target_y = from->y;

	int range = 1;

	if (this->world->eif->Get(from->paperdoll[Character::Weapon])->subtype == EIF::Ranged)
	{
		range = static_cast<int>(this->world->config["RangedDistance"]);
	}

	for (int i = 0; i < range; ++i)
	{
		switch (from->direction)
		{
			case DIRECTION_UP:
				target_y -= 1;
				break;

			case DIRECTION_RIGHT:
				target_x += 1;
				break;

			case DIRECTION_DOWN:
				target_y += 1;
				break;

			case DIRECTION_LEFT:
				target_x -= 1;
				break;
		}

		if (!this->Walkable(target_x, target_y, true))
  {
   break;
  }

		UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
		{
			if (character->mapid == this->id && !character->nowhere && character->x == target_x && character->y == target_y)
			{
			    Character *character_ptr = *character;
                    character_ptr->AddRef();

                        int itemid, effectid;
for(int i = 0 ; i < static_cast<int>(this->world->effects_config["WAmount"]) ; i++){
itemid = static_cast<int>(this->world->effects_config[util::to_string(i+1) + ".ItemID"]);
effectid = static_cast<int>(this->world->effects_config[util::to_string(i+1) + ".PlayerEffect"]);
       if(from->paperdoll[Character::Weapon] == itemid)
       {
           character_ptr->Effect(effectid, true);
       }
}
		if(from->clas == 9)// where it began
			    {
                    Character *character_ptr = *character;
                    character_ptr->AddRef();

                    int amount = util::rand(from->mindam + 0, from->maxdam + 0);
                    double rand = util::rand(0.0, 1.0);
                    // Checks if target is facing you
                    bool critical = std::abs(int(character_ptr->direction) - from->direction) != 2 || rand < static_cast<double>(this->world->config["CriticalRate"]);

                    std::tr1::unordered_map<std::string, double> formula_vars;

                    from->FormulaVars(formula_vars);
                    character_ptr->FormulaVars(formula_vars, "target_");
                    formula_vars["modifier"] = this->world->config["PKRate"];
                    formula_vars["damage"] = amount;
                    formula_vars["critical"] = critical;

                    amount = rpn_eval(rpn_parse(this->world->formulas_config["damage"]), formula_vars);
                    double hit_rate = rpn_eval(rpn_parse(this->world->formulas_config["hit_rate"]), formula_vars);

                    if (rand > hit_rate)
                    {
                        amount = 0;
                    }

                    amount = std::max(amount, 0);

                    int limitamount = std::min(amount, int(character_ptr->hp));

                    if (this->world->config["LimitDamage"])
                    {
                        amount = limitamount;
                    }

                    if (character_ptr->invincible == false && character_ptr->guild != from->guild)
                    {
                        character_ptr->hp -= limitamount;

                        PacketBuilder builder(PACKET_CLOTHES, PACKET_REPLY);
                        builder.AddShort(from->player->id);
                        builder.AddShort(character_ptr->player->id);
                        builder.AddThree(amount);
                        builder.AddChar(from->direction);
                        builder.AddChar(int(double(character_ptr->hp) / double(character_ptr->maxhp) * 100.0));
                        builder.AddChar(character_ptr->hp == 0);

                        UTIL_PTR_LIST_FOREACH(this->characters, Character, checkchar)
                        {
                            if (character_ptr->InRange(*checkchar))
                            {
                                checkchar->player->client->SendBuilder(builder);
                            }
                        }
                    }
                    else
                    {
                        PacketBuilder builder(PACKET_CLOTHES, PACKET_REPLY);
                        builder.AddShort(from->player->id);
                        builder.AddShort(character_ptr->player->id);
                        builder.AddThree(0);
                        builder.AddChar(from->direction);
                        builder.AddChar(int(double(character_ptr->hp) / double(character_ptr->maxhp) * 100.0));
                        builder.AddChar(character_ptr->hp == 0);

                        UTIL_PTR_LIST_FOREACH(this->characters, Character, checkchar)
                        {
                            if (character_ptr->InRange(*checkchar))
                            {
                                checkchar->player->client->SendBuilder(builder);
                            }
                        }

                    }

                    if (character_ptr->hp == 0)
                    {

Quest *temp_quest = 0;
State *state = 0;
UTIL_PTR_LIST_FOREACH(from->quests, Character_Quest, quest)
    {
    temp_quest = this->world->GetQuest(quest->id);
    if (!temp_quest) continue;

    state = temp_quest->GetState(quest->state);
    if (!state) continue;

    UTIL_PTR_VECTOR_FOREACH(state->rules, Rule, rule)
        {
        if (rule->name.compare("killedplayers") == 0)
            {
            quest->killed++;
        if (quest->killed >= ((int)(*rule->args[0])))
            {
            quest->killed = 0;
            quest->state = rule->goto_state;
            from->PerformQuestActions(quest->id);
            }
            break;
            }
        }
    }

std::string msg(character->name + " got KnocKed tHE FuK ouT By ");
msg += from->name;
this->world->ServerMsg(msg);

int item = 1;
int amount = 2000;
UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
            {
if (character->mapid == this->id && !character->nowhere && character->guild == from->guild)
			{
 Character *characterg = *character;
 characterg->AddRef();

    characterg->AddItem(item, amount);
    PacketBuilder builder(PACKET_ITEM, PACKET_GET);
    builder.AddShort(0); // UID
    builder.AddShort(item);
    builder.AddThree(amount);
    builder.AddChar(characterg->weight);
    builder.AddChar(characterg->maxweight);
    characterg->player->client->SendBuilder(builder);

 bool stats_updated = false;
characterg->exp += 1000;
stats_updated = true;
if (stats_updated)
    {
 bool level_up = false;
 while (characterg->level < static_cast<int>(this->world->config["MaxLevel"]) && characterg->exp >= this->world->exp_table[characterg->level+1])
        {
    level_up = true;
    ++from->level;
    characterg->statpoints += static_cast<int>(this->world->config["StatPerLevel"]);
    characterg->skillpoints += static_cast<int>(this->world->config["SkillPerLevel"]);
    characterg->CalculateStats();
        }

        PacketBuilder builder(PACKET_RECOVER, PACKET_REPLY);
        builder.AddInt(characterg->exp);
        builder.AddShort(characterg->karma);
        builder.AddChar(level_up ? characterg->level : 0);
        characterg->player->client->SendBuilder(builder);
       }
    }
  }

                        character_ptr->hp = int(character_ptr->maxhp * static_cast<double>(this->world->config["DeathRecover"]) / 100.0);

                        if (this->world->config["Deadly"])
                        {
                            character_ptr->DropAll(from);
                        }
character_ptr->PetTransfer();
                        character_ptr->map->Leave(character_ptr, WARP_ANIMATION_NONE, true);

                        character_ptr->nowhere = true;
                        character_ptr->map = this->world->GetMap(character_ptr->SpawnMap());
                        character_ptr->mapid = character_ptr->SpawnMap();
                        character_ptr->x = character_ptr->SpawnX();
                        character_ptr->y = character_ptr->SpawnY();
 character_ptr->PetTransfer();
                        PacketReader reader("");

                        character_ptr->player->client->queue.AddAction(PACKET_INTERNAL, PACKET_INTERNAL_NULL, reader, 1.5);
                        character_ptr->player->client->queue.AddAction(PACKET_INTERNAL, PACKET_INTERNAL_WARP, reader, 0.0);
                    }

                    PacketBuilder builder(PACKET_RECOVER, PACKET_PLAYER);
                    builder.AddShort(character_ptr->hp);
                    builder.AddInt(from->exp);
                    builder.AddShort(character_ptr->tp);
                    character_ptr->player->client->SendBuilder(builder);

                    character_ptr->Release();

                    return true;
			    }

			    else if(from->clas != 9)
			    {

                    int amount = util::rand(from->mindam, from->maxdam);
                    double rand = util::rand(0.0, 1.0);
                    // Checks if target is facing you
                    bool critical = std::abs(int(character_ptr->direction) - from->direction) != 2 || rand < static_cast<double>(this->world->config["CriticalRate"]);

                    std::tr1::unordered_map<std::string, double> formula_vars;

                    from->FormulaVars(formula_vars);
                    character_ptr->FormulaVars(formula_vars, "target_");
                    formula_vars["modifier"] = this->world->config["PKRate"];
                    formula_vars["damage"] = amount;
                    formula_vars["critical"] = critical;

                    amount = rpn_eval(rpn_parse(this->world->formulas_config["damage"]), formula_vars);
                    double hit_rate = rpn_eval(rpn_parse(this->world->formulas_config["hit_rate"]), formula_vars);

                    if (rand > hit_rate)
                    {
                        amount = 0;
                    }

                    amount = std::max(amount, 0);

                    int limitamount = std::min(amount, int(character_ptr->hp));

                    if (this->world->config["LimitDamage"])
                    {
                        amount = limitamount;
                    }

                    if (character_ptr->invincible == false && character_ptr->guild != from->guild)
                    {
                        character_ptr->hp -= limitamount;

                        PacketBuilder builder(PACKET_CLOTHES, PACKET_REPLY);
                        builder.AddShort(from->player->id);
                        builder.AddShort(character_ptr->player->id);
                        builder.AddThree(amount);
                        builder.AddChar(from->direction);
                        builder.AddChar(int(double(character_ptr->hp) / double(character_ptr->maxhp) * 100.0));
                        builder.AddChar(character_ptr->hp == 0);

                        UTIL_PTR_LIST_FOREACH(this->characters, Character, checkchar)
                        {
                            if (character_ptr->InRange(*checkchar))
                            {
                                checkchar->player->client->SendBuilder(builder);
                            }
                        }
                    }
                    else
                    {
                        PacketBuilder builder(PACKET_CLOTHES, PACKET_REPLY);
                        builder.AddShort(from->player->id);
                        builder.AddShort(character_ptr->player->id);
                        builder.AddThree(0);
                        builder.AddChar(from->direction);
                        builder.AddChar(int(double(character_ptr->hp) / double(character_ptr->maxhp) * 100.0));
                        builder.AddChar(character_ptr->hp == 0);

                        UTIL_PTR_LIST_FOREACH(this->characters, Character, checkchar)
                        {
                            if (character_ptr->InRange(*checkchar))
                            {
                                checkchar->player->client->SendBuilder(builder);
                            }
                        }

                    }

                    if (character_ptr->hp == 0)
                    {
                       Quest *temp_quest = 0;
State *state = 0;
UTIL_PTR_LIST_FOREACH(from->quests, Character_Quest, quest)
    {
    temp_quest = this->world->GetQuest(quest->id);
    if (!temp_quest) continue;

    state = temp_quest->GetState(quest->state);
    if (!state) continue;

    UTIL_PTR_VECTOR_FOREACH(state->rules, Rule, rule)
        {
        if (rule->name.compare("killedplayers") == 0)
            {
            quest->killed++;
        if (quest->killed >= ((int)(*rule->args[0])))
            {
            quest->killed = 0;
            quest->state = rule->goto_state;
            from->PerformQuestActions(quest->id);
            }
            break;
            }
        }
    }

this->world->ServerMsg(character->name + " got KnocKed tHE FuK ouT By " + from->name);
int item = 1;
int amount = 2000;
UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
            {
if (character->mapid == this->id && !character->nowhere && character->guild == from->guild)
			{
 Character *characterg = *character;
 characterg->AddRef();

    characterg->AddItem(item, amount);
    PacketBuilder builder(PACKET_ITEM, PACKET_GET);
    builder.AddShort(0); // UID
    builder.AddShort(item);
    builder.AddThree(amount);
    builder.AddChar(characterg->weight);
    builder.AddChar(characterg->maxweight);
    characterg->player->client->SendBuilder(builder);

 bool stats_updated = false;
characterg->exp += 1000;
stats_updated = true;
if (stats_updated)
    {
 bool level_up = false;
 while (characterg->level < static_cast<int>(this->world->config["MaxLevel"]) && characterg->exp >= this->world->exp_table[characterg->level+1])
        {
    level_up = true;
    ++from->level;
    characterg->statpoints += static_cast<int>(this->world->config["StatPerLevel"]);
    characterg->skillpoints += static_cast<int>(this->world->config["SkillPerLevel"]);
    characterg->CalculateStats();
        }

        PacketBuilder builder(PACKET_RECOVER, PACKET_REPLY);
        builder.AddInt(characterg->exp);
        builder.AddShort(characterg->karma);
        builder.AddChar(level_up ? characterg->level : 0);
        characterg->player->client->SendBuilder(builder);
       }
    }
  }

                        character_ptr->hp = int(character_ptr->maxhp * static_cast<double>(this->world->config["DeathRecover"]) / 100.0);

                        if (this->world->config["Deadly"])
                        {
                            character_ptr->DropAll(from);
                        }
 character_ptr->PetTransfer();
                        character_ptr->map->Leave(character_ptr, WARP_ANIMATION_NONE, true);

                        character_ptr->nowhere = true;
                        character_ptr->map = this->world->GetMap(character_ptr->SpawnMap());
                        character_ptr->mapid = character_ptr->SpawnMap();
                        character_ptr->x = character_ptr->SpawnX();
                        character_ptr->y = character_ptr->SpawnY();
 character_ptr->PetTransfer();
                        PacketReader reader("");

                        character_ptr->player->client->queue.AddAction(PACKET_INTERNAL, PACKET_INTERNAL_NULL, reader, 1.5);
                        character_ptr->player->client->queue.AddAction(PACKET_INTERNAL, PACKET_INTERNAL_WARP, reader, 0.0);
                    }

                    PacketBuilder builder(PACKET_RECOVER, PACKET_PLAYER);
                    builder.AddShort(character_ptr->hp);
                    builder.AddShort(character_ptr->tp);
                    character_ptr->player->client->SendBuilder(builder);

                    character_ptr->Release();

                    return true;
			    }
			}
		}
	}

	return false;
}

bool Map::AttackPKSpell(Character *from, int spellid, int targetid)
{
     ESF_Data *spell = this->world->esf->Get(spellid);

    PacketBuilder builder;

    UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
    {
        if (character->mapid == this->id && !character->nowhere && targetid == character->player->id && from->player->id != character->player->id)
        {
            Character *character_ptr = *character;
                character_ptr->AddRef();

           if (from->clas == 9)
            {
                 int amount = util::rand(spell->mindam * 1.5, spell->maxdam * 1.5);
                //int amount = util::rand(from->mindam + 0, from->maxdam + 0);
                int limitamount = std::min(amount, int(character_ptr->hp));

                if (static_cast<int>(this->world->config["LimitDamage"]))
                {
                    amount = limitamount;
                }

                if (character_ptr->invincible == false)
                {
                    character_ptr->hp -= limitamount;

                    builder.SetID(PACKET_CLOTHES, PACKET_ADMIN);
                    builder.AddShort(from->player->id);
                    builder.AddShort(character_ptr->player->id);
                    builder.AddThree(amount);
                    builder.AddChar(from->direction);
                    builder.AddChar(int(double(character_ptr->hp) / double(character_ptr->maxhp) * 100.0));
                    builder.AddChar(character_ptr->hp == 0);
                    builder.AddShort(spellid);

                    UTIL_PTR_LIST_FOREACH(this->characters, Character, checkchar)
                    {
                        if (character_ptr->InRange(*checkchar))
                        {
                            checkchar->player->client->SendBuilder(builder);
                        }
                    }
                }
                else
                {
                    builder.SetID(PACKET_CLOTHES, PACKET_ADMIN);
                    builder.AddShort(from->player->id);
                    builder.AddShort(character_ptr->player->id);
                    builder.AddThree(0);
                    builder.AddChar(from->direction);
                    builder.AddChar(int(double(character_ptr->hp) / double(character_ptr->maxhp) * 100.0));
                    builder.AddChar(character_ptr->hp == 0);
                    builder.AddShort(spellid);

                    UTIL_PTR_LIST_FOREACH(this->characters, Character, checkchar)
                    {
                        if (character_ptr->InRange(*checkchar))
                        {
                            checkchar->player->client->SendBuilder(builder);
                        }
                    }
                }

                if (character_ptr->hp == 0)
                {
                 Quest *temp_quest = 0;
    State *state = 0;
    UTIL_PTR_LIST_FOREACH(from->quests, Character_Quest, quest)
        {
        temp_quest = this->world->GetQuest(quest->id);
        if (!temp_quest) continue;

        state = temp_quest->GetState(quest->state);
        if (!state) continue;

        UTIL_PTR_VECTOR_FOREACH(state->rules, Rule, rule)
        {
        if (rule->name.compare("killedplayers") == 0)
            {
            quest->killed++;
        if (quest->killed >= ((int)(*rule->args[0])))
            {
            quest->killed = 0;
            quest->state = rule->goto_state;
            from->PerformQuestActions(quest->id);
            }
            break;
            }
        }
    }

std::string msg(character->name + " got KnocKed tHE FuK ouT By ");
msg += from->name;
this->world->ServerMsg(msg);

int item = 1;
int amount = 2000;
UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
            {
if (character->mapid == this->id && !character->nowhere && character->guild == from->guild)
			{
 Character *characterg = *character;
 characterg->AddRef();

    characterg->AddItem(item, amount);
    PacketBuilder builder(PACKET_ITEM, PACKET_GET);
    builder.AddShort(0); // UID
    builder.AddShort(item);
    builder.AddThree(amount);
    builder.AddChar(characterg->weight);
    builder.AddChar(characterg->maxweight);
    characterg->player->client->SendBuilder(builder);

 bool stats_updated = false;
characterg->exp += 1000;
stats_updated = true;
if (stats_updated)
    {
 bool level_up = false;
 while (characterg->level < static_cast<int>(this->world->config["MaxLevel"]) && characterg->exp >= this->world->exp_table[characterg->level+1])
        {
    level_up = true;
    ++from->level;
    characterg->statpoints += static_cast<int>(this->world->config["StatPerLevel"]);
    characterg->skillpoints += static_cast<int>(this->world->config["SkillPerLevel"]);
    characterg->CalculateStats();
        }

        PacketBuilder builder(PACKET_RECOVER, PACKET_REPLY);
        builder.AddInt(characterg->exp);
        builder.AddShort(characterg->karma);
        builder.AddChar(level_up ? characterg->level : 0);
        characterg->player->client->SendBuilder(builder);
       }
    }
  }
                    character_ptr->hp = int(character_ptr->maxhp * static_cast<double>(this->world->config["DeathRecover"]) / 100.0);

                    if (this->world->config["Deadly"])
                    {
                        character_ptr->DropAll(from);
                    }
 character_ptr->PetTransfer();
                    character_ptr->map->Leave(character_ptr, WARP_ANIMATION_NONE, true);

                    character_ptr->nowhere = true;
                    character_ptr->map = this->world->GetMap(character_ptr->SpawnMap());
                    character_ptr->mapid = character_ptr->SpawnMap();
                    character_ptr->x = character_ptr->SpawnX();
                    character_ptr->y = character_ptr->SpawnY();
 character_ptr->PetTransfer();
                    PacketReader reader("");

                    character_ptr->player->client->queue.AddAction(PACKET_INTERNAL, PACKET_INTERNAL_NULL, reader, 1.5);
                    character_ptr->player->client->queue.AddAction(PACKET_INTERNAL, PACKET_INTERNAL_WARP, reader, 0.0);
                }

                builder.Reset();
                builder.SetID(PACKET_RECOVER, PACKET_PLAYER);
                builder.AddShort(character_ptr->hp);
                builder.AddShort(character_ptr->tp);
                character_ptr->player->client->SendBuilder(builder);

                character_ptr->Release();

                return true;
            }

            else if (from->clas != 9)
            {

            int amount = util::rand(spell->mindam, spell->maxdam);
               // int amount = util::rand(from->mindam, from->maxdam);
                int limitamount = std::min(amount, int(character_ptr->hp));

                if (static_cast<int>(this->world->config["LimitDamage"]))
                {
                    amount = limitamount;
                }

                if (character_ptr->invincible == false)
                {
                    character_ptr->hp -= limitamount;

                    builder.SetID(PACKET_CLOTHES, PACKET_ADMIN);
                    builder.AddShort(from->player->id);
                    builder.AddShort(character_ptr->player->id);
                    builder.AddThree(amount);
                    builder.AddChar(from->direction);
                    builder.AddChar(int(double(character_ptr->hp) / double(character_ptr->maxhp) * 100.0));
                    builder.AddChar(character_ptr->hp == 0);
                    builder.AddShort(spellid);

                    UTIL_PTR_LIST_FOREACH(this->characters, Character, checkchar)
                    {
                        if (character_ptr->InRange(*checkchar))
                        {
                            checkchar->player->client->SendBuilder(builder);
                        }
                    }
                }
                else
                {
                    builder.SetID(PACKET_CLOTHES, PACKET_ADMIN);
                    builder.AddShort(from->player->id);
                    builder.AddShort(character_ptr->player->id);
                    builder.AddThree(0);
                    builder.AddChar(from->direction);
                    builder.AddChar(int(double(character_ptr->hp) / double(character_ptr->maxhp) * 100.0));
                    builder.AddChar(character_ptr->hp == 0);
                    builder.AddShort(spellid);

                    UTIL_PTR_LIST_FOREACH(this->characters, Character, checkchar)
                    {
                        if (character_ptr->InRange(*checkchar))
                        {
                            checkchar->player->client->SendBuilder(builder);
                        }
                    }
                }

                if (character_ptr->hp == 0)
                {

                    Quest *temp_quest = 0;
    State *state = 0;
    UTIL_PTR_LIST_FOREACH(from->quests, Character_Quest, quest)
        {
        temp_quest = this->world->GetQuest(quest->id);
        if (!temp_quest) continue;

        state = temp_quest->GetState(quest->state);
        if (!state) continue;

        UTIL_PTR_VECTOR_FOREACH(state->rules, Rule, rule)
        {
        if (rule->name.compare("killedplayers") == 0)
            {
            quest->killed++;
        if (quest->killed >= ((int)(*rule->args[0])))
            {
            quest->killed = 0;
            quest->state = rule->goto_state;
            from->PerformQuestActions(quest->id);
            }
            break;
            }
        }
    }

std::string msg(character->name + " got KnocKed tHE FuK ouT By ");
msg += from->name;
this->world->ServerMsg(msg);

int item = 1;
int amount = 2000;
UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
            {
if (character->mapid == this->id && !character->nowhere && character->guild == from->guild)
			{
 Character *characterg = *character;
 characterg->AddRef();

    characterg->AddItem(item, amount);
    PacketBuilder builder(PACKET_ITEM, PACKET_GET);
    builder.AddShort(0); // UID
    builder.AddShort(item);
    builder.AddThree(amount);
    builder.AddChar(characterg->weight);
    builder.AddChar(characterg->maxweight);
    characterg->player->client->SendBuilder(builder);

 bool stats_updated = false;
characterg->exp += 1000;
stats_updated = true;
if (stats_updated)
    {
 bool level_up = false;
 while (characterg->level < static_cast<int>(this->world->config["MaxLevel"]) && characterg->exp >= this->world->exp_table[characterg->level+1])
        {
    level_up = true;
    ++from->level;
    characterg->statpoints += static_cast<int>(this->world->config["StatPerLevel"]);
    characterg->skillpoints += static_cast<int>(this->world->config["SkillPerLevel"]);
    characterg->CalculateStats();
        }

        PacketBuilder builder(PACKET_RECOVER, PACKET_REPLY);
        builder.AddInt(characterg->exp);
        builder.AddShort(characterg->karma);
        builder.AddChar(level_up ? characterg->level : 0);
        characterg->player->client->SendBuilder(builder);
       }
    }
  }

                    character_ptr->hp = int(character_ptr->maxhp * static_cast<double>(this->world->config["DeathRecover"]) / 100.0);

                    if (this->world->config["Deadly"])
                    {
                        character_ptr->DropAll(from);
                    }
 character_ptr->PetTransfer();
                    character_ptr->map->Leave(character_ptr, WARP_ANIMATION_NONE, true);

                    character_ptr->nowhere = true;
                    character_ptr->map = this->world->GetMap(character_ptr->SpawnMap());
                    character_ptr->mapid = character_ptr->SpawnMap();
                    character_ptr->x = character_ptr->SpawnX();
                    character_ptr->y = character_ptr->SpawnY();
 character_ptr->PetTransfer();
                    PacketReader reader("");

                    character_ptr->player->client->queue.AddAction(PACKET_INTERNAL, PACKET_INTERNAL_NULL, reader, 1.5);
                    character_ptr->player->client->queue.AddAction(PACKET_INTERNAL, PACKET_INTERNAL_WARP, reader, 0.0);
                }

                builder.Reset();
                builder.SetID(PACKET_RECOVER, PACKET_PLAYER);
                builder.AddShort(character_ptr->hp);
                builder.AddShort(character_ptr->tp);
                character_ptr->player->client->SendBuilder(builder);

                character_ptr->Release();

                return true;
            }
        }
    }

return false;

}

void Map::ClassSpell(Character *from, int targetid)
{
PacketBuilder builder;
UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
                     {
                 Character *target = *character;
                target->AddRef();

                int spellid = util::rand(1, 31);
                int distance = util::path_length(target->x, target->y, from->x, from->y);
               builder.SetID(PACKET_CLOTHES, PACKET_ADMIN);
               builder.AddShort(0);
               builder.AddShort(target->player->id);
               builder.AddThree(0);
               builder.AddChar(1);
               builder.AddChar(int(double(target->hp) / double(target->maxhp) * 100.0));
               builder.AddChar(target->hp == 0);
               builder.AddShort(spellid);

               UTIL_PTR_LIST_FOREACH(this->characters, Character, checkchar)
                    {
                        if (target->InRange(*checkchar))
                        {
                            checkchar->player->client->SendBuilder(builder);
                            target->player->client->SendBuilder(builder);
                        }
                    }
                target->Effect(spellid, true);
                target->hp = target->maxhp;
                builder.Reset();
                builder.SetID(PACKET_RECOVER, PACKET_PLAYER);
                builder.AddShort(target->hp);
                builder.AddShort(target->tp);
                target->player->client->SendBuilder(builder);
    }
}

void Map::Face(Character *from, Direction direction)
{
	PacketBuilder builder;

	from->direction = direction;

	builder.SetID(PACKET_FACE, PACKET_PLAYER);
	builder.AddShort(from->player->id);
	builder.AddChar(direction);

	UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
	{
		if (*character == from || !from->InRange(*character))
		{
			continue;
		}

		character->player->client->SendBuilder(builder);
	}
}

void Map::Sit(Character *from, SitAction sit_type)
{
	PacketBuilder builder;

	from->sitting = sit_type;

	builder.SetID((sit_type == SIT_CHAIR) ? PACKET_CHAIR : PACKET_SIT, PACKET_PLAYER);
	builder.AddShort(from->player->id);
	builder.AddChar(from->x);
	builder.AddChar(from->y);
	builder.AddChar(from->direction);
	builder.AddChar(0); // ?

	UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
	{
		if (*character == from || !from->InRange(*character))
		{
			continue;
		}

		character->player->client->SendBuilder(builder);
	}
}

void Map::Stand(Character *from)
{
	PacketBuilder builder;

	from->sitting = SIT_STAND;

	builder.SetID(PACKET_SIT, PACKET_REMOVE);
	builder.AddShort(from->player->id);
	builder.AddChar(from->x);
	builder.AddChar(from->y);

	UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
	{
		if (*character == from || !from->InRange(*character))
		{
			continue;
		}

		character->player->client->SendBuilder(builder);
	}
}

void Map::Emote(Character *from, enum Emote emote, bool echo)
{

	PacketBuilder builder;

	builder.SetID(PACKET_EMOTE, PACKET_PLAYER);
	builder.AddShort(from->player->id);
	builder.AddChar(emote);

	UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
	{
		if (!echo && (*character == from || !from->InRange(*character)))
		{
			continue;
		}

		character->player->client->SendBuilder(builder);
	}
}

bool Map::Occupied(unsigned char x, unsigned char y, Map::OccupiedTarget target)
{
	if (x >= this->width || y >= this->height)
	{
		return false;
	}

	if (target != Map::NPCOnly)
	{
		UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
		{
			if (character->x == x && character->y == y)
			{
				return true;
			}
		}
	}

	if (target != Map::PlayerOnly)
	{
		UTIL_PTR_VECTOR_FOREACH(this->npcs, NPC, npc)
		{
			if (npc->alive && npc->x == x && npc->y == y)
			{
				return true;
			}
		}
	}

	return false;
}

void Map::Shine_God()
{
    UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
    {
    if(character->invincible == true)
    {
    character->Emote(EMOTE_ANGRY, true);
    }
    }
}

Map::~Map()
{
	this->Unload();
}

bool Map::OpenDoor(Character *from, unsigned char x, unsigned char y)
{
	if (from && !from->InRange(x, y))
	{
		return false;
	}

	if (Map_Warp *warp = this->GetWarp(x, y))
	{
		if (warp->spec == Map_Warp::NoDoor || warp->open)
		{
			return false;
		}

		  if (from && warp->spec > Map_Warp::Door)
    {
        if (!from->HasItem(this->world->eif->GetKey(warp->spec - static_cast<int>(Map_Warp::Door)) + 1))
        {
            return false;
        }
    }

		PacketBuilder builder;
		builder.SetID(PACKET_DOOR, PACKET_OPEN);
		builder.AddChar(x);
		builder.AddShort(y);

		UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
		{
			if (character->InRange(x, y))
			{
				character->player->client->SendBuilder(builder);
			}
		}

		warp->open = true;

		map_close_door_struct *close = new map_close_door_struct;
		close->map = this;
		close->x = x;
		close->y = y;

		TimeEvent *event = new TimeEvent(map_close_door, close, this->world->config["DoorTimer"], 1);
		this->world->timer.Register(event);
		event->Release();

		return true;
	}

	return false;
}

void Map::CloseDoor(unsigned char x, unsigned char y)
{
	if (Map_Warp *warp = this->GetWarp(x, y))
	{
		if (warp->spec == Map_Warp::NoDoor || !warp->open)
		{
			return;
		}

		warp->open = false;
	}
}

Map_Item *Map::AddItem(short id, int amount, unsigned char x, unsigned char y, Character *from)
{
	Map_Item *newitem(new Map_Item(GenerateItemID(), id, amount, x, y, 0, 0));

	PacketBuilder builder;
	builder.SetID(PACKET_ITEM, PACKET_ADD);
	builder.AddShort(id);
	builder.AddShort(newitem->uid);
	builder.AddThree(amount);
	builder.AddChar(x);
	builder.AddChar(y);

	if (from || (from && from->admin <= ADMIN_GM))
	{
		int ontile = 0;
		int onmap = 0;

		UTIL_PTR_LIST_FOREACH(this->items, Map_Item, item)
		{
			++onmap;
			if (item->x == x && item->y == y)
			{
				++ontile;
			}
		}

		if (ontile >= static_cast<int>(this->world->config["MaxTile"]) || onmap >= static_cast<int>(this->world->config["MaxMap"]))
		{
			return 0;
		}
	}

	UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
	{
		if ((from && *character == from) || !character->InRange(newitem))
		{
			continue;
		}
		character->player->client->SendBuilder(builder);
	}

	this->items.push_back(newitem);
	newitem->Release();
	return this->items.back();
}

Map_Item *Map::GetItem(short uid)
{
	UTIL_PTR_LIST_FOREACH(this->items, Map_Item, item)
	{
		if (item->uid == uid)
		{
			return *item;
		}
	}

	return 0;
}

void Map::DelItem(short uid, Character *from)
{
	UTIL_PTR_LIST_FOREACH(this->items, Map_Item, item)
	{
		if (item->uid == uid)
		{
			PacketBuilder builder;
			builder.SetID(PACKET_ITEM, PACKET_REMOVE);
			builder.AddShort(uid);
			UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
			{
				if ((from && *character == from) || !character->InRange(*item))
				{
					continue;
				}
				character->player->client->SendBuilder(builder);
			}
			this->items.erase(item);
			break;
		}
	}
}

void Map::DelItem(Map_Item *item_, Character *from)
{
	UTIL_PTR_LIST_FOREACH(this->items, Map_Item, item)
	{
		if (item_ == *item)
		{
			PacketBuilder builder;
			builder.SetID(PACKET_ITEM, PACKET_REMOVE);
			builder.AddShort(item->uid);
			UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
			{
				if ((from && *character == from) || !character->InRange(*item))
				{
					continue;
				}
				character->player->client->SendBuilder(builder);
			}
			this->items.erase(item);
			break;
		}
	}
}

bool Map::InBounds(unsigned char x, unsigned char y)
{
	return !(x >= this->width || y >= this->height);
}

bool Map::Walkable(unsigned char x, unsigned char y, bool npc)
{
	return (InBounds(x, y) && this->tiles[y]->at(x)->Walkable(npc));
}

Map_Tile::TileSpec Map::GetSpec(unsigned char x, unsigned char y)
{
	if (x >= this->width || y >= this->height)
	{
		return Map_Tile::None;
	}

	return this->tiles[y]->at(x)->tilespec;
}

Map_Warp *Map::GetWarp(unsigned char x, unsigned char y)
{
	if (x >= this->width || y >= this->height)
	{
		return 0;
	}

	return this->tiles[y]->at(x)->warp;
}

void Map::Effect(int effect, int param)
{
	PacketBuilder builder;
	builder.SetID(PACKET_EFFECT, PACKET_USE);
	builder.AddChar(effect);
	builder.AddChar(param);

	UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
	{
		character->player->client->SendBuilder(builder);
	}
}

bool Map::Reload()
{
	char namebuf[6];
	char checkrid[4];

	std::string filename = this->world->config["MapDir"];
	std::sprintf(namebuf, "%05i", this->id);
	this->filename = filename;
	filename.append(namebuf);
	filename.append(".emf");

	std::FILE *fh = std::fopen(filename.c_str(), "rb");

	if (!fh)
	{
		Console::Err("Could not load file: %s", filename.c_str());
		return false;
	}

	SAFE_SEEK(fh, 0x03, SEEK_SET);
	SAFE_READ(checkrid, sizeof(char), 4, fh);

	if (this->rid[0] == checkrid[0] && this->rid[1] == checkrid[1]
	 && this->rid[2] == checkrid[2] && this->rid[3] == checkrid[3])
	{
		return true;
	}

	PtrList<Character> temp = this->characters;

	this->Unload();

	if (!this->Load())
	{
		return false;
	}

	this->characters = temp;

	PacketBuilder builder(0);
	builder.AddChar(INIT_MAP_MUTATION);

	std::string content;
	std::fseek(fh, 0, SEEK_SET);
	do {
		char buf[4096];
		int len = std::fread(buf, sizeof(char), 4096, fh);
		content.append(buf, len);
	} while (!std::feof(fh));
	std::fclose(fh);

	builder.AddString(content);

	PacketBuilder protect_builder(0);
	protect_builder.AddChar(INIT_BANNED);

	UTIL_PTR_LIST_FOREACH(temp, Character, character)
	{
		character->player->client->Send(builder.Get());
		character->Refresh(); // TODO: Find a better way to reload NPCs

		if (this->world->config["ProtectMaps"])
		{
			character->player->client->Send(protect_builder.Get());
		}
	}

	this->exists = true;

	return true;
}

Character *Map::GetCharacter(std::string name)
{
	name = util::lowercase(name);

	UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
	{
		if (character->name.compare(name) == 0)
		{
			return *character;
		}
	}

	return 0;
}

Character *Map::GetCharacterPID(unsigned int id)
{
	UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
	{
		if (character->player->id == id)
		{
			return *character;
		}
	}

	return 0;
}

Character *Map::GetCharacterCID(unsigned int id)
{
	UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
	{
		if (character->id == id)
		{
			return *character;
		}
	}

	return 0;
}