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))
{
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;
}